inweb-bootstrap/docs/inweb/4-is.html
2020-04-17 10:07:57 +01:00

1466 lines
185 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>InC Support</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-src/Figures/Octagram184x184.png" width=72 height=72">
</a></h1>
<ul><li><a href="index.html"><span class="selectedlink">inweb</span></a></li>
</ul><h2>Foundation Module</h2><ul>
<li><a href="../foundation-module/index.html">foundation</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul><h2>Example Webs</h2><ul>
<li><a href="../goldbach/index.html">goldbach</a></li>
<li><a href="../twinprimes/twinprimes.html">twinprimes</a></li>
<li><a href="../eastertide/index.html">eastertide</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inform/docs/index.html">inform</a></li>
<li><a href="../../../intest/docs/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'InC Support' generated by Inweb-->
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>InC Support</b></li></ul><p class="purpose">To support a modest extension of C called InC.</p>
<ul class="toc"><li><a href="4-is.html#SP1">&#167;1. Creation</a></li><li><a href="4-is.html#SP3">&#167;3. Parsing methods</a></li><li><a href="4-is.html#SP3_1">&#167;3.1. Parsing Preform grammar</a></li><li><a href="4-is.html#SP3_1_1_1">&#167;3.1.1.1. Parsing the body of Preform grammar</a></li><li><a href="4-is.html#SP3_2">&#167;3.2. Parsing I-literals</a></li><li><a href="4-is.html#SP4">&#167;4. Tangling methods</a></li><li><a href="4-is.html#SP14">&#167;14. Weaving</a></li><li><a href="4-is.html#SP15">&#167;15. Weaving methods</a></li><li><a href="4-is.html#SP18">&#167;18. Analysis methods</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Creation. </b>As can be seen, InC is a basically C-like language, but in addition to having
all of those methods, it has a whole lot more of its own.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InCSupport::add_features<button class="popup" onclick="togglePopup('usagePopup194')">...<span class="popuptext" id="usagePopup194">Usage of <b>InCSupport::add_features</b>:<br>Programming Languages - <a href="4-pl.html#SP7_2">&#167;7.2</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">) {</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">FURTHER_PARSING_PAR_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP3">InCSupport::further_parsing</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">SUPPRESS_EXPANSION_TAN_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP4">InCSupport::suppress_expansion</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">TANGLE_COMMAND_TAN_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP5">InCSupport::special_tangle_command</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">ADDITIONAL_PREDECLARATIONS_TAN_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP6">InCSupport::additional_predeclarations</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">WILL_TANGLE_EXTRA_LINE_TAN_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP8">InCSupport::will_insert_in_tangle</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">TANGLE_EXTRA_LINE_TAN_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP9">InCSupport::insert_in_tangle</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">TANGLE_LINE_UNUSUALLY_TAN_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP10">InCSupport::tangle_line</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">GNABEHS_TAN_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP7">InCSupport::gnabehs</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">ADDITIONAL_TANGLING_TAN_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP13">InCSupport::additional_tangling</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">SKIP_IN_WEAVING_WEA_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP15">InCSupport::skip_in_weaving</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">WEAVE_CODE_LINE_WEA_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP16">InCSupport::weave_code_line</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">NOTIFY_NEW_TAG_WEA_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP17">InCSupport::new_tag_declared</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">ANALYSIS_ANA_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP18">InCSupport::analyse_code</a></span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">SHARE_ELEMENT_ANA_MTID</span><span class="plain">, </span><span class="functiontext"><a href="4-is.html#SP18">InCSupport::share_element</a></span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>We will apply this special tag wherever Preform grammar is defined:
</p>
<pre class="display">
<span class="reserved">theme_tag</span><span class="plain"> *</span><span class="identifier">Preform_theme</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. Parsing methods. </b>We only provide one parsing method, but it's a big one:
</p>
<pre class="display">
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">alphabetical_list_of_nonterminals</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InCSupport::further_parsing<button class="popup" onclick="togglePopup('usagePopup195')">...<span class="popuptext" id="usagePopup195">Usage of <b>InCSupport::further_parsing</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_WITHIN_TANGLE</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="functiontext"><a href="3-tt.html#SP4">Tangler::primary_target</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
&lt;<span class="cwebmacro">Detect and deal with Preform grammar</span> <span class="cwebmacronumber">3.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Detect and deal with I-literals</span> <span class="cwebmacronumber">3.2</span>&gt;
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3_1"></a><b>&#167;3.1. Parsing Preform grammar. </b>This is where we look for declarations of nonterminals. Very little about
the following code will make sense unless you've first read the Preform
section of the <code class="display"><span class="extract">words</span></code> module, which is what we're supporting, and seen
some examples of Preform being used in the Inform source code.
</p>
<p class="inwebparagraph">In parsing, we categorise the opening lines <code class="display"><span class="extract">PREFORM_LCAT</span></code>. Subsequent lines
of grammar are <code class="display"><span class="extract">PREFORM_GRAMMAR_LCAT</span></code>; but the lines of InC code inside an
<code class="display"><span class="extract">internal</span></code> definition remain just plain <code class="display"><span class="extract">CODE_BODY_LCAT</span></code> lines.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NOT_A_NONTERMINAL</span><span class="plain"> -4</span>
<span class="definitionkeyword">define</span> <span class="constant">A_FLEXIBLE_NONTERMINAL</span><span class="plain"> -3</span>
<span class="definitionkeyword">define</span> <span class="constant">A_VORACIOUS_NONTERMINAL</span><span class="plain"> -2</span>
<span class="definitionkeyword">define</span> <span class="constant">A_GRAMMAR_NONTERMINAL</span><span class="plain"> -1</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Detect and deal with Preform grammar</span> <span class="cwebmacronumber">3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">form</span><span class="plain"> = </span><span class="constant">NOT_A_NONTERMINAL</span><span class="plain">; </span><span class="comment"> one of the four values above, or a non-negative word count</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">pntname</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">header</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Parse a Preform nonterminal header line</span> <span class="cwebmacronumber">3.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">form</span><span class="plain"> != </span><span class="constant">NOT_A_NONTERMINAL</span><span class="plain">) </span>&lt;<span class="cwebmacro">Record a Preform nonterminal here</span> <span class="cwebmacronumber">3.1.3</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">pntname</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">header</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_1"></a><b>&#167;3.1.1. </b>The keyword <code class="display"><span class="extract">internal</span></code> can be followed by an indication of the number
of words the nonterminal will match: usually a decimal non-negative number,
but optionally a question mark <code class="display"><span class="extract">?</span></code> to indicate voracity.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Parse a Preform nonterminal header line</span> <span class="cwebmacronumber">3.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(&lt;%p+&gt;) ::=%c*"</span><span class="plain">)) {</span>
<span class="identifier">form</span><span class="plain"> = </span><span class="constant">A_GRAMMAR_NONTERMINAL</span><span class="plain">;</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">pntname</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">header</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
&lt;<span class="cwebmacro">Parse the subsequent lines as Preform grammar</span> <span class="cwebmacronumber">3.1.1.1</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="identifier">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"((&lt;%p+&gt;) internal %?) {%c*"</span><span class="plain">)) {</span>
<span class="identifier">form</span><span class="plain"> = </span><span class="constant">A_VORACIOUS_NONTERMINAL</span><span class="plain">;</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">pntname</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">header</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="identifier">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"((&lt;%p+&gt;) internal) {%c*"</span><span class="plain">)) {</span>
<span class="identifier">form</span><span class="plain"> = </span><span class="constant">A_FLEXIBLE_NONTERMINAL</span><span class="plain">;</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">pntname</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">header</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="identifier">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"((&lt;%p+&gt;) internal (%d+)) {%c*"</span><span class="plain">)) {</span>
<span class="identifier">form</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP7">Str::atoi</a></span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[2], </span><span class="constant">0</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">pntname</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">header</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="plain">}</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1">&#167;3.1</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_2"></a><b>&#167;3.1.2. </b>Each Preform nonterminal defined in the tangle will cause one of these
structures to be created:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">preform_nonterminal</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">nt_name</span><span class="plain">; </span><span class="comment"> e.g., <code class="display"><span class="extract">&lt;action-clause&gt;</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">unangled_name</span><span class="plain">; </span><span class="comment"> e.g., <code class="display"><span class="extract">action-clause</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">as_C_identifier</span><span class="plain">; </span><span class="comment"> e.g., <code class="display"><span class="extract">action_clause_NTM</span></code></span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">as_function</span><span class="plain">; </span><span class="comment"> defined internally, that is, parsed by a C language_function</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">voracious</span><span class="plain">; </span><span class="comment"> a voracious nonterminal: see "The English Syntax of Inform"</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">min_word_count</span><span class="plain">; </span><span class="comment"> for internals only</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">max_word_count</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">takes_pointer_result</span><span class="plain">; </span><span class="comment"> right-hand formula defines <code class="display"><span class="extract">*XP</span></code>, not <code class="display"><span class="extract">*X</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">where_defined</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">next_pnt_alphabetically</span><span class="plain">;</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">preform_nonterminal</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure preform_nonterminal is accessed in 3/ta, 4/taf, 5/tf and here.</p>
<p class="inwebparagraph"><a id="SP3_1_3"></a><b>&#167;3.1.3. </b>We will
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Record a Preform nonterminal here</span> <span class="cwebmacronumber">3.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">pnt</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">preform_nonterminal</span><span class="plain">);</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">where_defined</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">nt_name</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">pntname</span><span class="plain">);</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">unangled_name</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">pntname</span><span class="plain">);</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">pntname</span><span class="plain">);</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">next_pnt_alphabetically</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Apply unangling cream to name</span> <span class="cwebmacronumber">3.1.3.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compose a C identifier for the nonterminal</span> <span class="cwebmacronumber">3.1.3.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Work out the parsing characteristics of the nonterminal</span> <span class="cwebmacronumber">3.1.3.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Insertion-sort this this nonterminal into the alphabetical list</span> <span class="cwebmacronumber">3.1.3.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Register the nonterminal with the line and paragraph from which it comes</span> <span class="cwebmacronumber">3.1.3.5</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1">&#167;3.1</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_3_1"></a><b>&#167;3.1.3.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Apply unangling cream to name</span> <span class="cwebmacronumber">3.1.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">pntname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"%&lt;(%c*)%&gt;"</span><span class="plain">)) </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">unangled_name</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1_3">&#167;3.1.3</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_3_2"></a><b>&#167;3.1.3.2. </b>When the program we are tangling is eventually running, each nonterminal
will be represented by a pointer to a unique data structure for it. Inweb
automatically compiles code to create these pointers; and here's how it
works out their names.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compose a C identifier for the nonterminal</span> <span class="cwebmacronumber">3.1.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP24">Str::delete_first_character</a></span><span class="plain">(</span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="identifier">as_C_identifier</span><span class="plain">);</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get</a></span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) == </span><span class="character">'-'</span><span class="plain">) </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP14">Str::put</a></span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="character">'_'</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get</a></span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) == </span><span class="character">'&gt;'</span><span class="plain">) { </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP14">Str::put</a></span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="constant">0</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">; }</span>
<span class="plain">}</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain">, </span><span class="string">"_NTM"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1_3">&#167;3.1.3</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_3_3"></a><b>&#167;3.1.3.3. </b>"Artamène ou le Grand Cyrus", by Georges or possibly his sister Madeleine
de Scudéry, published around 1650, runs to 1,954,300 words. If you can write
an Inform source text 500 times longer than that, then you may need to raise
the following definition:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">INFINITE_WORD_COUNT</span><span class="plain"> </span><span class="constant">1000000000</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Work out the parsing characteristics of the nonterminal</span> <span class="cwebmacronumber">3.1.3.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">voracious</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">form</span><span class="plain"> == </span><span class="constant">A_VORACIOUS_NONTERMINAL</span><span class="plain">) </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">voracious</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_function</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">form</span><span class="plain"> == </span><span class="constant">A_GRAMMAR_NONTERMINAL</span><span class="plain">) </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_function</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">takes_pointer_result</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">nt_name</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"&lt;k-%c+"</span><span class="plain">)) </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">takes_pointer_result</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">nt_name</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"&lt;s-%c+"</span><span class="plain">)) </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">takes_pointer_result</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">min</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">max</span><span class="plain"> = </span><span class="identifier">form</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">form</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">max</span><span class="plain"> = </span><span class="constant">INFINITE_WORD_COUNT</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">max</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">min</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">max</span><span class="plain"> != </span><span class="constant">INFINITE_WORD_COUNT</span><span class="plain">) </span><span class="identifier">min</span><span class="plain"> = </span><span class="identifier">max</span><span class="plain">;</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">min_word_count</span><span class="plain"> = </span><span class="identifier">min</span><span class="plain">;</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">max_word_count</span><span class="plain"> = </span><span class="identifier">max</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1_3">&#167;3.1.3</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_3_4"></a><b>&#167;3.1.3.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Insertion-sort this this nonterminal into the alphabetical list</span> <span class="cwebmacronumber">3.1.3.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">alphabetical_list_of_nonterminals</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">alphabetical_list_of_nonterminals</span><span class="plain"> = </span><span class="identifier">pnt</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">placed</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">last</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">seq</span><span class="plain"> = </span><span class="identifier">alphabetical_list_of_nonterminals</span><span class="plain">; </span><span class="identifier">seq</span><span class="plain">;</span>
<span class="identifier">seq</span><span class="plain"> = </span><span class="identifier">seq</span><span class="plain">-&gt;</span><span class="identifier">next_pnt_alphabetically</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP19">Str::cmp</a></span><span class="plain">(</span><span class="identifier">pntname</span><span class="plain">, </span><span class="identifier">seq</span><span class="plain">-&gt;</span><span class="element">nt_name</span><span class="plain">) &lt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">seq</span><span class="plain"> == </span><span class="identifier">alphabetical_list_of_nonterminals</span><span class="plain">) {</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">next_pnt_alphabetically</span><span class="plain"> = </span><span class="identifier">alphabetical_list_of_nonterminals</span><span class="plain">;</span>
<span class="identifier">alphabetical_list_of_nonterminals</span><span class="plain"> = </span><span class="identifier">pnt</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">last</span><span class="plain">-&gt;</span><span class="element">next_pnt_alphabetically</span><span class="plain"> = </span><span class="identifier">pnt</span><span class="plain">;</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">next_pnt_alphabetically</span><span class="plain"> = </span><span class="identifier">seq</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">placed</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">last</span><span class="plain"> = </span><span class="identifier">seq</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">placed</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) </span><span class="identifier">last</span><span class="plain">-&gt;</span><span class="element">next_pnt_alphabetically</span><span class="plain"> = </span><span class="identifier">pnt</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1_3">&#167;3.1.3</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_3_5"></a><b>&#167;3.1.3.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Register the nonterminal with the line and paragraph from which it comes</span> <span class="cwebmacronumber">3.1.3.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">preform_nonterminal_defined</span><span class="plain"> = </span><span class="identifier">pnt</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Preform_theme</span><span class="plain">) </span><span class="functiontext"><a href="2-tgs.html#SP3">Tags::add_to_paragraph</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">, </span><span class="identifier">Preform_theme</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> = </span><span class="constant">PREFORM_LCAT</span><span class="plain">;</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text_operand</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">header</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1_3">&#167;3.1.3</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_1_1"></a><b>&#167;3.1.1.1. Parsing the body of Preform grammar. </b>After a line like <code class="display"><span class="extract">&lt;action-clause&gt; ::=</span></code>, Preform grammar follows on subsequent
lines until we hit the end of the paragraph, or a white-space line, whichever
comes first. Each line of grammar is categorised <code class="display"><span class="extract">PREFORM_GRAMMAR_LCAT</span></code>.
If we have a line with an arrow, like so:
</p>
<pre class="display">
<span class="plain">porcupine tree ==&gt; 2</span>
</pre>
<p class="inwebparagraph">then the text on the left goes into <code class="display"><span class="extract">text_operand</span></code> and the right into
<code class="display"><span class="extract">text_operand2</span></code>, with the arrow itself (and white space around it) cut out.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Parse the subsequent lines as Preform grammar</span> <span class="cwebmacronumber">3.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">AL</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">AL</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">; (</span><span class="identifier">AL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">CODE_BODY_LCAT</span><span class="plain">); </span><span class="identifier">AL</span><span class="plain"> = </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP5">Regexp::string_is_white_space</a></span><span class="plain">(</span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> = </span><span class="constant">PREFORM_GRAMMAR_LCAT</span><span class="plain">;</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+) ==&gt; (%c*)"</span><span class="plain">)) {</span>
<span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand2</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand</span><span class="plain"> = </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">;</span>
<span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand2</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP2">Str::new</a></span><span class="plain">();</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Remove any C comment from the left side of the arrow</span> <span class="cwebmacronumber">3.1.1.1.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Detect any nonterminal variables being set on the right side of the arrow</span> <span class="cwebmacronumber">3.1.1.1.2</span>&gt;<span class="plain">;</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1_1">&#167;3.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_1_1_1"></a><b>&#167;3.1.1.1.1. </b>In case we have a comment at the end of the grammar, like this:
</p>
<pre class="display">
<span class="plain">porcupine tree /* what happens now? */</span>
</pre>
<p class="inwebparagraph">we want to remove it. The regular expression here isn't terribly legible, but
trust me, it's correct.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Remove any C comment from the left side of the arrow</span> <span class="cwebmacronumber">3.1.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c*)%/%*%c*%*%/ *"</span><span class="plain">))</span>
<span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1_1_1">&#167;3.1.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_1_1_2"></a><b>&#167;3.1.1.1.2. </b>Note that nonterminal variables are, by default, integers. If their names
are divided internally with a colon, however, as <code class="display"><span class="extract">&lt;&lt;structure:name&gt;&gt;</span></code>, then
they have the type <code class="display"><span class="extract">structure *</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Detect any nonterminal variables being set on the right side of the arrow</span> <span class="cwebmacronumber">3.1.1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">to_scan</span><span class="plain">); </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">to_scan</span><span class="plain">, </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand2</span><span class="plain">);</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">to_scan</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"%c*?&lt;&lt;(%P+?)&gt;&gt; =(%c*)"</span><span class="plain">)) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">var_given</span><span class="plain">); </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">var_given</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">type_given</span><span class="plain">); </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">type_given</span><span class="plain">, </span><span class="string">"int"</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">to_scan</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">var_given</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%p+):%p+"</span><span class="plain">)) {</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP15">Str::clear</a></span><span class="plain">(</span><span class="identifier">type_given</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">type_given</span><span class="plain">, </span><span class="string">"%S *"</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="plain">}</span>
<span class="reserved">nonterminal_variable</span><span class="plain"> *</span><span class="identifier">ntv</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ntv</span><span class="plain">, </span><span class="reserved">nonterminal_variable</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP18">Str::eq</a></span><span class="plain">(</span><span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">ntv_name</span><span class="plain">, </span><span class="identifier">var_given</span><span class="plain">))</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ntv</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span>&lt;<span class="cwebmacro">This one's new, so create a new nonterminal variable</span> <span class="cwebmacronumber">3.1.1.1.2.2</span>&gt;<span class="character">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">var_given</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">type_given</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">to_scan</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1_1_1">&#167;3.1.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP3_1_1_1_2_1"></a><b>&#167;3.1.1.1.2.1. </b>Nonterminal variables are actually just global C variables, and their C
identifiers need to avoid hyphens and colons. For example, <code class="display"><span class="extract">&lt;&lt;kind:ref&gt;&gt;</span></code>
has identifier <code class="display"><span class="extract">"kind_ref_NTMV"</span></code>. Each one is recorded in a structure thus:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">nonterminal_variable</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">ntv_name</span><span class="plain">; </span><span class="comment"> e.g., <code class="display"><span class="extract">"num"</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">ntv_type</span><span class="plain">; </span><span class="comment"> e.g., <code class="display"><span class="extract">"int"</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">ntv_identifier</span><span class="plain">; </span><span class="comment"> e.g., <code class="display"><span class="extract">"num_NTMV"</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">first_mention</span><span class="plain">; </span><span class="comment"> first usage</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">nonterminal_variable</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure nonterminal_variable is private to this section.</p>
<p class="inwebparagraph"><a id="SP3_1_1_1_2_2"></a><b>&#167;3.1.1.1.2.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">This one's new, so create a new nonterminal variable</span> <span class="cwebmacronumber">3.1.1.1.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">ntv</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">nonterminal_variable</span><span class="plain">);</span>
<span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">ntv_name</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">var_given</span><span class="plain">);</span>
<span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">ntv_type</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">type_given</span><span class="plain">);</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">var_given</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get</a></span><span class="plain">(</span><span class="identifier">P</span><span class="plain">) == </span><span class="character">'-'</span><span class="plain">) || (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get</a></span><span class="plain">(</span><span class="identifier">P</span><span class="plain">) == </span><span class="character">':'</span><span class="plain">))</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP14">Str::put</a></span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="character">'_'</span><span class="plain">);</span>
<span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">ntv_identifier</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP2">Str::new</a></span><span class="plain">();</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">ntv_identifier</span><span class="plain">, </span><span class="string">"%S_NTMV"</span><span class="plain">, </span><span class="identifier">var_given</span><span class="plain">);</span>
<span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">first_mention</span><span class="plain"> = </span><span class="identifier">AL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_1_1_1_2">&#167;3.1.1.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP3_2"></a><b>&#167;3.2. Parsing I-literals. </b>A simpler but useful further addition to C is that we recognise a new form
of string literal: <code class="display"><span class="extract">I"quartz"</span></code> makes a constant text stream with the content
"quartz".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Detect and deal with I-literals</span> <span class="cwebmacronumber">3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">quoted</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">; </span><span class="identifier">i</span><span class="plain"> &lt; </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP8">Str::len</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="character">'"'</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">-1) != </span><span class="character">'\\'</span><span class="plain">) &amp;&amp;</span>
<span class="plain">((</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">-1) != </span><span class="character">'\''</span><span class="plain">) || (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1) != </span><span class="character">'\''</span><span class="plain">)))</span>
<span class="identifier">quoted</span><span class="plain"> = </span><span class="identifier">quoted</span><span class="plain">?</span><span class="identifier">FALSE:TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">fundamental_mode</span><span class="plain"> != </span><span class="constant">WEAVE_MODE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">quoted</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="character">'I'</span><span class="plain">) &amp;&amp; (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1) == </span><span class="character">'"'</span><span class="plain">))</span>
&lt;<span class="cwebmacro">This looks like an I-literal</span> <span class="cwebmacronumber">3.2.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP3_2_1"></a><b>&#167;3.2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">This looks like an I-literal</span> <span class="cwebmacronumber">3.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">lit</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i_was</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ended</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">i</span><span class="plain"> += </span><span class="constant">2</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="character">'"'</span><span class="plain">) { </span><span class="identifier">ended</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">; }</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">lit</span><span class="plain">, </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">++));</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ended</span><span class="plain">) </span>&lt;<span class="cwebmacro">This is definitely an I-literal</span> <span class="cwebmacronumber">3.2.1.2</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">lit</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_2">&#167;3.2</a>.</p>
<p class="inwebparagraph"><a id="SP3_2_1_1"></a><b>&#167;3.2.1.1. </b>Each I-literal results in an instance of the following being created. The
I-literal <code class="display"><span class="extract">I"quartz"</span></code> would have content <code class="display"><span class="extract">quartz</span></code> and identifier something
like <code class="display"><span class="extract">TL_IS_123</span></code>.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_literal</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">tl_identifier</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">tl_content</span><span class="plain">;</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">text_literal</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure text_literal is private to this section.</p>
<p class="inwebparagraph"><a id="SP3_2_1_2"></a><b>&#167;3.2.1.2. </b>So suppose we've got a line of web such as
</p>
<pre class="display">
<span class="plain">text_stream *T = I"quartz";</span>
</pre>
<p class="inwebparagraph">We create the necessary I-literal, and splice the line so that it now reads
<code class="display"><span class="extract">text_stream *T = TL_IS_123;</span></code>. (That's why we don't call any of this on a
weave run; we're actually amending the code of the web.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">This is definitely an I-literal</span> <span class="cwebmacronumber">3.2.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">text_literal</span><span class="plain"> *</span><span class="identifier">tl</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">text_literal</span><span class="plain">);</span>
<span class="identifier">tl</span><span class="plain">-&gt;</span><span class="element">tl_identifier</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP2">Str::new</a></span><span class="plain">();</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">-&gt;</span><span class="element">tl_identifier</span><span class="plain">, </span><span class="string">"TL_IS_%d"</span><span class="plain">, </span><span class="identifier">tl</span><span class="plain">-&gt;</span><span class="element">allocation_id</span><span class="plain">);</span>
<span class="identifier">tl</span><span class="plain">-&gt;</span><span class="element">tl_content</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP3">Str::duplicate</a></span><span class="plain">(</span><span class="identifier">lit</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">before</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">after</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy</a></span><span class="plain">(</span><span class="identifier">before</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP15">Str::truncate</a></span><span class="plain">(</span><span class="identifier">before</span><span class="plain">, </span><span class="identifier">i_was</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP16">Str::copy_tail</a></span><span class="plain">(</span><span class="identifier">after</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP15">Str::clear</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="string">"%S%S"</span><span class="plain">, </span><span class="identifier">before</span><span class="plain">, </span><span class="identifier">tl</span><span class="plain">-&gt;</span><span class="element">tl_identifier</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP8">Str::len</a></span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">after</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">before</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">after</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP3_2_1">&#167;3.2.1</a>.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Tangling methods. </b>Suppress the expansion of macros occurring on a line introduced by a <code class="display"><span class="extract">//</span></code>
comment. (This avoids problems when tangling code that's been commented out.)
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InCSupport::suppress_expansion<button class="popup" onclick="togglePopup('usagePopup196')">...<span class="popuptext" id="usagePopup196">Usage of <b>InCSupport::suppress_expansion</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">material</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">material</span><span class="plain">, </span><span class="constant">0</span><span class="plain">) == </span><span class="character">'/'</span><span class="plain">) &amp;&amp; (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">material</span><span class="plain">, </span><span class="constant">1</span><span class="plain">) == </span><span class="character">'/'</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>InC does three things which C doesn't: it allows the namespaced function
names like <code class="display"><span class="extract">Section::function()</span></code>; it allows Foundation-class-style string
literals marked with an I, <code class="display"><span class="extract">I"like this"</span></code>, which we will call I-literals;
and it allows Preform natural language grammar to be mixed in with code.
</p>
<p class="inwebparagraph">The following routine is a hook needed for two of these. It recognises
two special tangling commands:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) <code class="display"><span class="extract">[[nonterminals]]</span></code> tangles to code which initialises the Preform
grammar. (The grammar defines the meaning of nonterminals such as
<code class="display"><span class="extract">&lt;sentence&gt;</span></code>. They're not terminal in the sense that they are defined
as combinations of other things.) In practice, this needs to appear once
in any program using Preform. For the Inform project, that's done in the
<code class="display"><span class="extract">words</span></code> module of the Inform 7 compiler.
</li></ul>
<ul class="items"><li>(b) <code class="display"><span class="extract">[[textliterals]]</span></code> tangles to code which initialises the I-literals.
</li></ul>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InCSupport::special_tangle_command<button class="popup" onclick="togglePopup('usagePopup197')">...<span class="popuptext" id="usagePopup197">Usage of <b>InCSupport::special_tangle_command</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">me</span><span class="plain">, </span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">data</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">data</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"nonterminals"</span><span class="plain">)) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"register_tangled_nonterminals();\n"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">data</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"textliterals"</span><span class="plain">)) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"register_tangled_text_literals();\n"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Time to predeclare things. InC is going to create a special function, right
at the end of the code, which "registers" the nonterminals, creating their
run-time data structures; we must predeclare this function. It will set values
for the pointers <code class="display"><span class="extract">action_clause_NTM</span></code>, and so on; these are global variables,
which we initially declare as <code class="display"><span class="extract">NULL</span></code>.
</p>
<p class="inwebparagraph">We also declare the nonterminal variables like <code class="display"><span class="extract">kind_ref_NTMV</span></code>, initialising
all integers to zero and all pointers to <code class="display"><span class="extract">NULL</span></code>.
</p>
<p class="inwebparagraph">We do something similar, but simpler, to declare text stream constants.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InCSupport::additional_predeclarations<button class="popup" onclick="togglePopup('usagePopup198')">...<span class="popuptext" id="usagePopup198">Usage of <b>InCSupport::additional_predeclarations</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_WITHIN_TANGLE</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="functiontext"><a href="3-tt.html#SP4">Tangler::primary_target</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">preform_nonterminal_defined</span><span class="plain">) {</span>
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">pnt</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">preform_nonterminal_defined</span><span class="plain">;</span>
<span class="functiontext"><a href="4-lm.html#SP15">LanguageMethods::insert_line_marker</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"nonterminal *%S = NULL;\n"</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">nonterminal_variable</span><span class="plain"> *</span><span class="identifier">ntv</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ntv</span><span class="plain">, </span><span class="reserved">nonterminal_variable</span><span class="plain">)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S %S = %s;\n"</span><span class="plain">,</span>
<span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">ntv_type</span><span class="plain">, </span><span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">ntv_identifier</span><span class="plain">,</span>
<span class="plain">(</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">ntv_type</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"int"</span><span class="plain">))?</span><span class="string">"0"</span><span class="plain">:</span><span class="string">"NULL"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"void register_tangled_nonterminals(void);\n"</span><span class="plain">);</span>
<span class="reserved">text_literal</span><span class="plain"> *</span><span class="identifier">tl</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">, </span><span class="reserved">text_literal</span><span class="plain">)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"text_stream *%S = NULL;\n"</span><span class="plain">, </span><span class="identifier">tl</span><span class="plain">-&gt;</span><span class="element">tl_identifier</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"void register_tangled_text_literals(void);\n"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>And here are the promised routines, which appear at the very end of the code.
They make use of macros and data structures defined in the Inform 7 web.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InCSupport::gnabehs<button class="popup" onclick="togglePopup('usagePopup199')">...<span class="popuptext" id="usagePopup199">Usage of <b>InCSupport::gnabehs</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"void register_tangled_nonterminals(void) {\n"</span><span class="plain">);</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_WITHIN_TANGLE</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="functiontext"><a href="3-tt.html#SP4">Tangler::primary_target</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">preform_nonterminal_defined</span><span class="plain">) {</span>
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">pnt</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">preform_nonterminal_defined</span><span class="plain">;</span>
<span class="functiontext"><a href="4-lm.html#SP15">LanguageMethods::insert_line_marker</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_function</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\tINTERNAL_NONTERMINAL(L\"%S\", %S, %d, %d);\n"</span><span class="plain">,</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">nt_name</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain">,</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">min_word_count</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">max_word_count</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\t%S-&gt;voracious = %d;\n"</span><span class="plain">,</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">voracious</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\tREGISTER_NONTERMINAL(L\"%S\", %S);\n"</span><span class="plain">,</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">nt_name</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"}\n"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"void register_tangled_text_literals(void) {\n"</span><span class="plain">); </span><span class="constant">INDENT</span><span class="plain">;</span>
<span class="reserved">text_literal</span><span class="plain"> *</span><span class="identifier">tl</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">, </span><span class="reserved">text_literal</span><span class="plain">)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S = Str::literal(L\"%S\");\n"</span><span class="plain">, </span><span class="identifier">tl</span><span class="plain">-&gt;</span><span class="element">tl_identifier</span><span class="plain">, </span><span class="identifier">tl</span><span class="plain">-&gt;</span><span class="element">tl_content</span><span class="plain">);</span>
<span class="constant">OUTDENT</span><span class="plain">; </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"}\n"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>That's it for big structural additions to the tangled C code. Now we turn
to how to tangle the lines we've given special categories to.
</p>
<p class="inwebparagraph">We need to tangle <code class="display"><span class="extract">PREFORM_LCAT</span></code> lines (those holding nonterminal declarations)
in a special way...
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InCSupport::will_insert_in_tangle<button class="popup" onclick="togglePopup('usagePopup200')">...<span class="popuptext" id="usagePopup200">Usage of <b>InCSupport::will_insert_in_tangle</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">PREFORM_LCAT</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>...and this is how. As can be seen, each nonterminal turns into a C function.
In the case of an internal definition, like
</p>
<pre class="display">
<span class="plain">&lt;k-kind-for-template&gt; internal {</span>
</pre>
<p class="inwebparagraph">we tangle this opening line to
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_kind_for_template_NTM</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> **</span><span class="identifier">XP</span><span class="plain">) {</span>
</pre>
<p class="inwebparagraph">that is, to a function which returns <code class="display"><span class="extract">TRUE</span></code> if it makes a match on the text
excerpt in Inform's source text, <code class="display"><span class="extract">FALSE</span></code> otherwise; if it matches and produces
an integer and/or pointer result, these are copied into <code class="display"><span class="extract">*X</span></code> and <code class="display"><span class="extract">*XP</span></code>. The
remaining lines of the function are tangled unaltered, i.e., following the
same rules as for the body of any other C function.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InCSupport::insert_in_tangle<button class="popup" onclick="togglePopup('usagePopup201')">...<span class="popuptext" id="usagePopup201">Usage of <b>InCSupport::insert_in_tangle</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">, </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">pnt</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">preform_nonterminal_defined</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_function</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"int %SR(wording W, int *X, void **XP) {\n"</span><span class="plain">,</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"int %SC(int *X, void **XP, int *R, void **RP, wording *FW, wording W) {\n"</span><span class="plain">,</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Compile the body of the compositor function</span> <span class="cwebmacronumber">9.1</span>&gt;<span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"}\n"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9_1"></a><b>&#167;9.1. </b>On the other hand, a grammar nonterminal tangles to a "compositor function".
Thus the opening line
</p>
<pre class="display">
<span class="plain">&lt;action-clause&gt; ::=</span>
</pre>
<p class="inwebparagraph">tangles to a function header:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">action_clause_NTMC</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> **</span><span class="identifier">XP</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> **</span><span class="identifier">RP</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> *</span><span class="identifier">FW</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
</pre>
<p class="inwebparagraph">Subsequent lines of the nonterminal are categorised <code class="display"><span class="extract">PREFORM_GRAMMAR_LCAT</span></code>
and thus won't tangle to code at all, by the usual rules; so we tangle from
them directly here.
</p>
<p class="inwebparagraph">Composition is what happens after a successful match of the text in the
word range <code class="display"><span class="extract">W</span></code>. The idea is that, especially if the pattern was
complicated, we will need to "compose" the results of parsing individual
pieces of it into a result for the whole. These partial results can be found
in the arrays <code class="display"><span class="extract">R[n]</span></code> and <code class="display"><span class="extract">RP[n]</span></code> passed as parameters; recall that every
nonterminal has in principle both an integer and a pointer result, though
often one or both is undefined.
</p>
<p class="inwebparagraph">A simple example would be
</p>
<pre class="display">
<span class="plain">&lt;cardinal-number&gt; + &lt;cardinal-number&gt; ==&gt; R[1] + R[2]</span>
</pre>
<p class="inwebparagraph">where the composition function would be called on a match of, say, "\(5 + 7\)",
and would find the values 5 and 7 in <code class="display"><span class="extract">R[1]</span></code> and <code class="display"><span class="extract">R[2]</span></code> respectively. It would
then add these together, store 12 in <code class="display"><span class="extract">*X</span></code>, and return <code class="display"><span class="extract">TRUE</span></code> to show that all
was well.
</p>
<p class="inwebparagraph">A more typical example, drawn from the actual Inform 7 web, is:
</p>
<pre class="display">
<span class="plain">&lt;k-kind-of-kind&gt; &lt;k-formal-kind-variable&gt; ==&gt; Kinds::variable_construction(R[2], RP[1])</span>
</pre>
<p class="inwebparagraph">which says that the composite result &mdash; the right-hand formula &mdash; is formed by
calling a particular routine on the integer result of subexpression 2
(<code class="display"><span class="extract">&lt;k-formal-kind-variable&gt;</span></code>) and the pointer result of subexpression 1
(<code class="display"><span class="extract">&lt;k-kind-of-kind&gt;</span></code>). The answer, the composite result, that is, must be
placed in <code class="display"><span class="extract">*X</span></code> and <code class="display"><span class="extract">*XP</span></code>. (Composition functions are also allowed to
invalidate the result, by returning <code class="display"><span class="extract">FALSE</span></code>, and have other tricks up their
sleeves, but none of that is handled by Inweb: see the Inform 7 web for more
on this.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile the body of the compositor function</span> <span class="cwebmacronumber">9.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">needs_collation</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">AL</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">;</span>
<span class="plain">((</span><span class="identifier">AL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">PREFORM_GRAMMAR_LCAT</span><span class="plain">));</span>
<span class="identifier">AL</span><span class="plain"> = </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP8">Str::len</a></span><span class="plain">(</span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand2</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">needs_collation</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">needs_collation</span><span class="plain">) </span>&lt;<span class="cwebmacro">At least one of the grammar lines provided an arrow and formula</span> <span class="cwebmacronumber">9.1.2</span>&gt;
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">None of the grammar lines provided an arrow and formula</span> <span class="cwebmacronumber">9.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\treturn TRUE;\n"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP9_1_1"></a><b>&#167;9.1.1. </b>In the absence of any <code class="display"><span class="extract">==&gt;</span></code> formulae, we simply set <code class="display"><span class="extract">*X</span></code> to the default
result supplied; this is the production number within the grammar (0 for the
first line, 1 for the second, and so on) by default, with an undefined pointer.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">None of the grammar lines provided an arrow and formula</span> <span class="cwebmacronumber">9.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\t*X = R[0];\n"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP9_1">&#167;9.1</a>.</p>
<p class="inwebparagraph"><a id="SP9_1_2"></a><b>&#167;9.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">At least one of the grammar lines provided an arrow and formula</span> <span class="cwebmacronumber">9.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\tswitch(R[0]) {\n"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">AL</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">;</span>
<span class="plain">((</span><span class="identifier">AL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">PREFORM_GRAMMAR_LCAT</span><span class="plain">));</span>
<span class="identifier">AL</span><span class="plain"> = </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">++) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">formula</span><span class="plain"> = </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand2</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP8">Str::len</a></span><span class="plain">(</span><span class="identifier">formula</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\t\tcase %d: "</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Tangle the formula on the right-hand side of the arrow</span> <span class="cwebmacronumber">9.1.2.1</span>&gt;<span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">";\n"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"#pragma clang diagnostic push\n"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"#pragma clang diagnostic ignored \"-Wunreachable-code\"\n"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"break;\n"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"#pragma clang diagnostic pop\n"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\t\tdefault: *X = R[0]; break;\n"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\t}\n"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP9_1">&#167;9.1</a>.</p>
<p class="inwebparagraph"><a id="SP9_1_2_1"></a><b>&#167;9.1.2.1. </b>We assume that the RHS of the arrow is an expression to be evaluated,
and that it produces an integer or a pointer according to what the
non-terminal expects as its main result. But we make one exception: if
the formula begins with a paragraph macro, then it can't be an expression,
and instead we read it as code in a void context. (This code will, we
assume, set <code class="display"><span class="extract">*X</span></code> and/or <code class="display"><span class="extract">*XP</span></code> in some ingenious way of its own.)
</p>
<p class="inwebparagraph">Within the body of the formula, we allow a pseudo-macro to work: <code class="display"><span class="extract">WR[n]</span></code>
expands to word range <code class="display"><span class="extract">n</span></code> in the match which we're compositing. This actually
expands like so:
</p>
<pre class="display">
<span class="identifier">action_clause_NTM</span><span class="plain">-&gt;</span><span class="identifier">range_result</span><span class="plain">[</span><span class="identifier">n</span><span class="plain">]</span>
</pre>
<p class="inwebparagraph">which saves a good deal of typing. (A regular C preprocessor macro couldn't
easily do this, because it needs to include the identifier name of the
nonterminal being parsed.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Tangle the formula on the right-hand side of the arrow</span> <span class="cwebmacronumber">9.1.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (!</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">formula</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"@&lt;%c*"</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">takes_pointer_result</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"*XP = "</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"*X = "</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">expanded</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"> &lt; </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP8">Str::len</a></span><span class="plain">(</span><span class="identifier">formula</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">formula</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="character">'W'</span><span class="plain">) &amp;&amp; (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">formula</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1) == </span><span class="character">'R'</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">formula</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+2) == </span><span class="character">'['</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">isdigit</span><span class="plain">(</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">formula</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+3))) &amp;&amp; (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">formula</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+4) == </span><span class="character">']'</span><span class="plain">)) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">expanded</span><span class="plain">,</span>
<span class="string">"%S-&gt;range_result[%c]"</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain">, </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">formula</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+3));</span>
<span class="identifier">i</span><span class="plain"> += </span><span class="constant">4</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">expanded</span><span class="plain">, </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">formula</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="functiontext"><a href="3-tt.html#SP3">Tangler::tangle_line</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">expanded</span><span class="plain">, </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">, </span><span class="identifier">AL</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">expanded</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP9_1_2">&#167;9.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>Going down from line level to the tangling of little excerpts of C code,
we also provide for some other special extensions to C.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InCSupport::tangle_line<button class="popup" onclick="togglePopup('usagePopup202')">...<span class="popuptext" id="usagePopup202">Usage of <b>InCSupport::tangle_line</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">original</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">fcall_pos</span><span class="plain"> = -1;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">i</span><span class="plain"> &lt; </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP8">Str::len</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
&lt;<span class="cwebmacro">Double-colons are namespace dividers in function names</span> <span class="cwebmacronumber">10.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="character">'&lt;'</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1) == </span><span class="character">'&lt;'</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Double-angles sometimes delimit Preform variable names</span> <span class="cwebmacronumber">10.2</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
&lt;<span class="cwebmacro">Single-angles sometimes delimit Preform nonterminal names</span> <span class="cwebmacronumber">10.3</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> == </span><span class="identifier">fcall_pos</span><span class="plain">) {</span>
<span class="identifier">fcall_pos</span><span class="plain"> = -1;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", NULL, NULL"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10_1"></a><b>&#167;10.1. </b>For example, a function name like <code class="display"><span class="extract">Text::Parsing::get_next</span></code> must be rewritten
as <code class="display"><span class="extract">Text__Parsing__get_next</span></code> since colons aren't valid in C identifiers. The
following is prone to all kinds of misreadings, of course; it picks up any use
of <code class="display"><span class="extract">::</span></code> between an alphanumberic character and a letter. In particular, code
like
</p>
<pre class="display">
<span class="plain">printf("Trying Text::Parsing::get_next now.\n");</span>
</pre>
<p class="inwebparagraph">will be rewritten as
</p>
<pre class="display">
<span class="identifier">printf</span><span class="plain">(</span><span class="string">"Trying Text__Parsing__get_next now.\n"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph">This is probably unwanted, but it doesn't matter, because these Inform-only
extension features of Inweb aren't intended for general use: only for
Inform, where no misreadings occur.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Double-colons are namespace dividers in function names</span> <span class="cwebmacronumber">10.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="character">':'</span><span class="plain">) &amp;&amp; (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1) == </span><span class="character">':'</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">isalpha</span><span class="plain">(</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+2))) &amp;&amp; (</span><span class="identifier">isalnum</span><span class="plain">(</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">-1)))) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"__"</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_2"></a><b>&#167;10.2. </b>Angle brackets around a valid Preform variable name expand into its
C identifier; for example, <code class="display"><span class="extract">&lt;&lt;R&gt;&gt;</span></code> becomes <code class="display"><span class="extract">most_recent_result</span></code>.
We take no action if it's not a valid name, so <code class="display"><span class="extract">&lt;&lt;fish&gt;&gt;</span></code> becomes
just <code class="display"><span class="extract">&lt;&lt;fish&gt;&gt;</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Double-angles sometimes delimit Preform variable names</span> <span class="cwebmacronumber">10.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">check_this</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP25">Str::substr</a></span><span class="plain">(</span><span class="identifier">check_this</span><span class="plain">, </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP10">Str::at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">), </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP10">Str::end</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">check_this</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"&lt;&lt;(%P+)&gt;&gt;%c*"</span><span class="plain">)) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">putative</span><span class="plain"> = </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0];</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">pv_identifier</span><span class="plain"> = </span><span class="functiontext"><a href="4-is.html#SP12">InCSupport::nonterminal_variable_identifier</a></span><span class="plain">(</span><span class="identifier">putative</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pv_identifier</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">pv_identifier</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain"> += </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP8">Str::len</a></span><span class="plain">(</span><span class="identifier">putative</span><span class="plain">) + </span><span class="constant">3</span><span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">check_this</span><span class="plain">);</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">check_this</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_3"></a><b>&#167;10.3. </b>Similarly for nonterminals; <code class="display"><span class="extract">&lt;k-kind&gt;</span></code> might become <code class="display"><span class="extract">k_kind_NTM</span></code>.
Here, though, there's a complication:
</p>
<pre class="display">
<span class="plain">if (&lt;k-kind&gt;(W)) { ...</span>
</pre>
<p class="inwebparagraph">must expand to:
</p>
<pre class="display">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Text__Languages__parse_nt_against_word_range</span><span class="plain">(</span><span class="identifier">k_kind_NTM</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">)) { ...</span>
</pre>
<p class="inwebparagraph">This is all syntactic sugar to make it easier to see parsing in action.
Anyway, it means we have to set <code class="display"><span class="extract">fcall_pos</span></code> to remember to add in the
two <code class="display"><span class="extract">NULL</span></code> arguments when we hit the <code class="display"><span class="extract">)</span></code> a little later. We're doing all
of this fairly laxly, but as before: it only needs to work for Inform,
and Inform doesn't cause any trouble.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Single-angles sometimes delimit Preform nonterminal names</span> <span class="cwebmacronumber">10.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">check_this</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-sm.html#SP25">Str::substr</a></span><span class="plain">(</span><span class="identifier">check_this</span><span class="plain">, </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP10">Str::at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">), </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP10">Str::end</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">check_this</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(&lt;%p+&gt;)%c*"</span><span class="plain">)) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">putative</span><span class="plain"> = </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0];</span>
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">pnt</span><span class="plain"> = </span><span class="functiontext"><a href="4-is.html#SP11">InCSupport::nonterminal_by_name</a></span><span class="plain">(</span><span class="identifier">putative</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pnt</span><span class="plain">) {</span>
<span class="identifier">i</span><span class="plain"> += </span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP8">Str::len</a></span><span class="plain">(</span><span class="identifier">putative</span><span class="plain">) - </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1) == </span><span class="character">'('</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">arity</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">+2, </span><span class="identifier">bl</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">; ((</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">bl</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">)); </span><span class="identifier">j</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">) == </span><span class="character">'('</span><span class="plain">) </span><span class="identifier">bl</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">) == </span><span class="character">')'</span><span class="plain">) { </span><span class="identifier">bl</span><span class="plain">--; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bl</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">fcall_pos</span><span class="plain"> = </span><span class="identifier">j</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP13">Str::get_at</a></span><span class="plain">(</span><span class="identifier">original</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">) == </span><span class="character">','</span><span class="plain">) &amp;&amp; (</span><span class="identifier">bl</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">)) </span><span class="identifier">arity</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Preform__parse_nt_against_word_range("</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_C_identifier</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fcall_pos</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", "</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">check_this</span><span class="plain">);</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">check_this</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>We needed two little routines to find nonterminals and their variables by
name. They're not very efficient, but experience shows that even on a web
the size of Inform 7, there's no significant gain from speeding them up
(with, say, a hash table).
</p>
<pre class="display">
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="functiontext">InCSupport::nonterminal_by_name<button class="popup" onclick="togglePopup('usagePopup203')">...<span class="popuptext" id="usagePopup203">Usage of <b>InCSupport::nonterminal_by_name</b>:<br><a href="4-is.html#SP10_3">&#167;10.3</a></span></button></span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">pnt</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">pnt</span><span class="plain">, </span><span class="reserved">preform_nonterminal</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP18">Str::eq</a></span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">nt_name</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pnt</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>The special variables <code class="display"><span class="extract">&lt;&lt;R&gt;&gt;</span></code> and <code class="display"><span class="extract">&lt;&lt;RP&gt;&gt;</span></code> hold the results,
integer and pointer, for the most recent successful match. They're defined
in the Inform 7 web (see the code for parsing text against Preform grammars),
not by Inweb.
</p>
<pre class="display">
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">InCSupport::nonterminal_variable_identifier<button class="popup" onclick="togglePopup('usagePopup204')">...<span class="popuptext" id="usagePopup204">Usage of <b>InCSupport::nonterminal_variable_identifier</b>:<br><a href="4-is.html#SP10_2">&#167;10.2</a></span></button></span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"r"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"most_recent_result"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"rp"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"most_recent_result_p"</span><span class="plain">;</span>
<span class="reserved">nonterminal_variable</span><span class="plain"> *</span><span class="identifier">ntv</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ntv</span><span class="plain">, </span><span class="reserved">nonterminal_variable</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP18">Str::eq</a></span><span class="plain">(</span><span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">ntv_name</span><span class="plain">, </span><span class="identifier">name</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ntv</span><span class="plain">-&gt;</span><span class="element">ntv_identifier</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>We saw above that the grammar lines following a non-internal declaration
were divided into actual grammar, then an arrow, then a formula. The formulae
were tangled into "composition functions", but the grammar itself was
simply thrown away. It doesn't appear anywhere in the C code tangled by
Inweb.
</p>
<p class="inwebparagraph">So what does happen to it? The answer is that it's transcribed into an
auxiliary file called <code class="display"><span class="extract">Syntax.preform</span></code>, which Inform, once it is compiled,
will read in at run-time. This is how that happens:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InCSupport::additional_tangling<button class="popup" onclick="togglePopup('usagePopup205')">...<span class="popuptext" id="usagePopup205">Usage of <b>InCSupport::additional_tangling</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">tangle_target</span><span class="plain"> *</span><span class="identifier">target</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="reserved">preform_nonterminal</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">pathname</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext"><a href="2-tr.html#SP7">Reader::tangled_folder</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">Syntax</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/3-fln.html#SP2">Filenames::in</a></span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Syntax.preform"</span><span class="plain">);</span>
<span class="reserved">text_stream</span><span class="plain"> </span><span class="identifier">TO_struct</span><span class="plain">;</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain"> = &amp;</span><span class="identifier">TO_struct</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">STREAM_OPEN_TO_FILE</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">Syntax</span><span class="plain">, </span><span class="constant">ISO_ENC</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="functiontext"><a href="../foundation-module/3-em.html#SP2">Errors::fatal_with_file</a></span><span class="plain">(</span><span class="string">"unable to write Preform file"</span><span class="plain">, </span><span class="identifier">Syntax</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="string">"Writing Preform syntax to: %/f\n"</span><span class="plain">, </span><span class="identifier">Syntax</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"[Preform syntax generated by inweb: do not edit.]\n\n"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/8-bdfw.html#SP6">Bibliographic::data_exists</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Preform Language"</span><span class="plain">))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"language %S\n"</span><span class="plain">, </span><span class="functiontext"><a href="../foundation-module/8-bdfw.html#SP6">Bibliographic::get_datum</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Preform Language"</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Actually write out the Preform syntax</span> <span class="cwebmacronumber">13.1</span>&gt;<span class="plain">;</span>
<span class="identifier">STREAM_CLOSE</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP13_1"></a><b>&#167;13.1. </b>See the "English Syntax of Inform" document for a heavily annotated
form of the result of the following. Note a useful convention: if the
right-hand side of the arrow in a grammar line uses a paragraph macro which
mentions a problem message, then we transcribe a Preform comment to that
effect. (This really is a comment: Inform ignores it, but it makes the
file more comprehensible to human eyes.) For example,
</p>
<pre class="display">
<span class="plain">&lt;article&gt; kind ==&gt; @&lt;Issue C8PropertyOfKind problem@&gt;</span>
</pre>
<p class="inwebparagraph">(The code in this paragraph macro will indeed issue this problem message, we
assume.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Actually write out the Preform syntax</span> <span class="cwebmacronumber">13.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_WITHIN_TANGLE</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">target</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">PREFORM_LCAT</span><span class="plain">) {</span>
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">pnt</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">preform_nonterminal_defined</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_function</span><span class="plain">)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n%S internal\n"</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">nt_name</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n%S ::=\n"</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text_operand</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">AL</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">;</span>
<span class="plain">((</span><span class="identifier">AL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">PREFORM_GRAMMAR_LCAT</span><span class="plain">));</span>
<span class="identifier">AL</span><span class="plain"> = </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand</span><span class="plain">);</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text_operand2</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"%c+Issue (%c+) problem%c+"</span><span class="plain">))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"[issues %S]"</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP13">&#167;13</a>.</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Weaving. </b>The following isn't a method, but is called by the weaver directly. It adds
additional endnotes to the woven form of a paragraph which includes Preform
nonterminal definitions:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InCSupport::weave_grammar_index<button class="popup" onclick="togglePopup('usagePopup206')">...<span class="popuptext" id="usagePopup206">Usage of <b>InCSupport::weave_grammar_index</b>:<br>The Weaver - <a href="3-tw.html#SP1_3_4_1_2">&#167;1.3.4.1.2</a></span></button></span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\\raggedright\\tolerance=10000"</span><span class="plain">);</span>
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">pnt</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pnt</span><span class="plain"> = </span><span class="identifier">alphabetical_list_of_nonterminals</span><span class="plain">; </span><span class="identifier">pnt</span><span class="plain">;</span>
<span class="identifier">pnt</span><span class="plain"> = </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="identifier">next_pnt_alphabetically</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\\line{\\nonterminal{%S}%s"</span>
<span class="string">"\\leaders\\hbox to 1em{\\hss.\\hss}\\hfill {\\xreffont %S}}\n"</span><span class="plain">,</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">unangled_name</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">as_function</span><span class="plain">)?</span><span class="string">" (internal)"</span><span class="plain">:</span><span class="string">""</span><span class="plain">,</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">where_defined</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">sect_range</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">said_something</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">List where the nonterminal appears in other Preform declarations</span> <span class="cwebmacronumber">14.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">List where the nonterminal is called from Inform code</span> <span class="cwebmacronumber">14.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">said_something</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\\par\\hangindent=3em{\\it unused}\n\n"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\\penalty-1000\n"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\\smallbreak\n"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\\hrule\\smallbreak\n"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP14_1"></a><b>&#167;14.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">List where the nonterminal is called from Inform code</span> <span class="cwebmacronumber">14.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">section</span><span class="plain">) </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">scratch_flag</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">hash_table_entry</span><span class="plain"> *</span><span class="identifier">hte</span><span class="plain"> = </span><span class="functiontext"><a href="3-ta.html#SP9">Analyser::find_hash_entry_for_section</a></span><span class="plain">(</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">where_defined</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">unangled_name</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">);</span>
<span class="reserved">hash_table_entry_usage</span><span class="plain"> *</span><span class="identifier">hteu</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">hteu</span><span class="plain">, </span><span class="reserved">hash_table_entry_usage</span><span class="plain">, </span><span class="identifier">hte</span><span class="plain">-&gt;</span><span class="element">usages</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">hteu</span><span class="plain">-&gt;</span><span class="identifier">form_of_usage</span><span class="plain"> &amp; </span><span class="constant">PREFORM_IN_CODE_USAGE</span><span class="plain">)</span>
<span class="identifier">hteu</span><span class="plain">-&gt;</span><span class="element">usage_recorded_at</span><span class="plain">-&gt;</span><span class="element">under_section</span><span class="plain">-&gt;</span><span class="element">scratch_flag</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">use_count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">section</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">scratch_flag</span><span class="plain">)</span>
<span class="identifier">use_count</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">use_count</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">said_something</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\\par\\hangindent=3em{\\it called from} "</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">section</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">scratch_flag</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">++ &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", "</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"{\\xreffont %S}"</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">sect_range</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n\n"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP14_2"></a><b>&#167;14.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">List where the nonterminal appears in other Preform declarations</span> <span class="cwebmacronumber">14.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">section</span><span class="plain">) </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">scratch_flag</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">hash_table_entry</span><span class="plain"> *</span><span class="identifier">hte</span><span class="plain"> = </span><span class="functiontext"><a href="3-ta.html#SP9">Analyser::find_hash_entry_for_section</a></span><span class="plain">(</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">where_defined</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">, </span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">unangled_name</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">);</span>
<span class="reserved">hash_table_entry_usage</span><span class="plain"> *</span><span class="identifier">hteu</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">hteu</span><span class="plain">, </span><span class="reserved">hash_table_entry_usage</span><span class="plain">, </span><span class="identifier">hte</span><span class="plain">-&gt;</span><span class="element">usages</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">hteu</span><span class="plain">-&gt;</span><span class="identifier">form_of_usage</span><span class="plain"> &amp; </span><span class="constant">PREFORM_IN_GRAMMAR_USAGE</span><span class="plain">)</span>
<span class="identifier">hteu</span><span class="plain">-&gt;</span><span class="element">usage_recorded_at</span><span class="plain">-&gt;</span><span class="element">under_section</span><span class="plain">-&gt;</span><span class="element">scratch_flag</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">use_count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">section</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">scratch_flag</span><span class="plain">)</span>
<span class="identifier">use_count</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">use_count</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">said_something</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\\par\\hangindent=3em{\\it used by other nonterminals in} "</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">section</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">scratch_flag</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">++ &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", "</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"{\\xreffont %S}"</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">sect_range</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n\n"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="4-is.html#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Weaving methods. </b>If we're weaving just a document of Preform grammar, then we skip any lines
of C code which appear in <code class="display"><span class="extract">internal</span></code> nonterminal definitions:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">skipping_internal</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">, </span><span class="identifier">preform_production_count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InCSupport::skip_in_weaving<button class="popup" onclick="togglePopup('usagePopup207')">...<span class="popuptext" id="usagePopup207">Usage of <b>InCSupport::skip_in_weaving</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">weave_order</span><span class="plain"> *</span><span class="identifier">wv</span><span class="plain">, </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Preform_theme</span><span class="plain">) &amp;&amp; (</span><span class="identifier">wv</span><span class="plain">-&gt;</span><span class="element">theme_match</span><span class="plain"> == </span><span class="identifier">Preform_theme</span><span class="plain">)) {</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::create_mr</a></span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"}%c*"</span><span class="plain">)) {</span>
<span class="identifier">skipping_internal</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">; </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">skipping_internal</span><span class="plain">) { </span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-pm.html#SP10">Regexp::match</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"&lt;%c*?&gt; internal%c*"</span><span class="plain">)) </span><span class="identifier">skipping_internal</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="functiontext"><a href="../foundation-module/4-pm.html#SP9">Regexp::dispose_of</a></span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. </b>And here is the TeX code for displaying Preform grammar:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InCSupport::weave_code_line<button class="popup" onclick="togglePopup('usagePopup208')">...<span class="popuptext" id="usagePopup208">Usage of <b>InCSupport::weave_code_line</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">,</span>
<span class="reserved">weave_order</span><span class="plain"> *</span><span class="identifier">wv</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">, </span><span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">,</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">matter</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">concluding_comment</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Preform_theme</span><span class="plain">) &amp;&amp; (</span><span class="identifier">wv</span><span class="plain">-&gt;</span><span class="element">theme_match</span><span class="plain"> == </span><span class="identifier">Preform_theme</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext"><a href="5-fm.html#SP29">Formats::preform_document</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">wv</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">,</span>
<span class="identifier">matter</span><span class="plain">, </span><span class="identifier">concluding_comment</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>In paragraphs where we spot Preform nonterminals being defined, we're
going to automatically apply the tag <code class="display"><span class="extract">^"Preform"</span></code>, but only if it already
exists. We watch for it here:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InCSupport::new_tag_declared<button class="popup" onclick="togglePopup('usagePopup209')">...<span class="popuptext" id="usagePopup209">Usage of <b>InCSupport::new_tag_declared</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">theme_tag</span><span class="plain"> *</span><span class="identifier">tag</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">tag</span><span class="plain">-&gt;</span><span class="element">tag_name</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Preform"</span><span class="plain">)) </span><span class="identifier">Preform_theme</span><span class="plain"> = </span><span class="identifier">tag</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. Analysis methods. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InCSupport::analyse_code<button class="popup" onclick="togglePopup('usagePopup210')">...<span class="popuptext" id="usagePopup210">Usage of <b>InCSupport::analyse_code</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">preform_nonterminal</span><span class="plain"> *</span><span class="identifier">pnt</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">pnt</span><span class="plain">, </span><span class="reserved">preform_nonterminal</span><span class="plain">)</span>
<span class="functiontext"><a href="3-ta.html#SP9">Analyser::find_hash_entry_for_section</a></span><span class="plain">(</span><span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">where_defined</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">,</span>
<span class="identifier">pnt</span><span class="plain">-&gt;</span><span class="element">unangled_name</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InCSupport::share_element<button class="popup" onclick="togglePopup('usagePopup211')">...<span class="popuptext" id="usagePopup211">Usage of <b>InCSupport::share_element</b>:<br><a href="4-is.html#SP1">&#167;1</a></span></button></span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">elname</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"word_ref1"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"word_ref2"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"next"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"down"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"allocation_id"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="../foundation-module/4-sm.html#SP21">Str::eq_wide_string</a></span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"method_set"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<hr class="tocbar">
<ul class="toc"><li><a href="4-cl.html">Back to 'C-Like Languages'</a></li><li><i>(This section ends Chapter 4: Languages.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="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>
</main>
</body>
</html>