1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/docs/words-module/4-lp.html

772 lines
138 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Loading Preform</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Preform-Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../indocn.html">indoc</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
<li><a href="../inrtpsn.html">inrtps</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inweb/index.html">inweb</a></li>
<li><a href="../../../intest/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Loading Preform' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../services.html">Services</a></li><li><a href="index.html">words</a></li><li><a href="index.html#4">Chapter 4: Parsing</a></li><li><b>Loading Preform</b></li></ul></div>
<p class="purpose">To read in structural definitions of natural language written in the meta-language Preform.</p>
<ul class="toc"><li><a href="4-lp.html#SP1">&#167;1. Reading Preform syntax from a file or text</a></li><li><a href="4-lp.html#SP5">&#167;5. Reserved words in Preform</a></li><li><a href="4-lp.html#SP7">&#167;7. Parsing Preform</a></li><li><a href="4-lp.html#SP8">&#167;8. Production lists</a></li><li><a href="4-lp.html#SP11">&#167;11. Productions and ptokens</a></li><li><a href="4-lp.html#SP14">&#167;14. Reading productions</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Reading Preform syntax from a file or text. </b>The parser reads source text against a specific language only, if
<span class="extract"><span class="extract-syntax">primary_Preform_language</span></span> is set; or, if it isn't, from any language.
</p>
<pre class="definitions code-font"><span class="definition-keyword">default</span> <span class="constant-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> </span><span class="reserved-syntax">void</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="constant-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">primary_Preform_language</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">LoadPreform::load</span><span class="plain-syntax">(</span><span class="identifier-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="constant-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">primary_Preform_language</span><span class="plain-syntax"> = </span><span class="identifier-syntax">L</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="4-lp.html#SP7" class="function-link"><span class="function-syntax">LoadPreform::parse</span></a><span class="plain-syntax">(</span><a href="4-lp.html#SP2" class="function-link"><span class="function-syntax">LoadPreform::feed_from_Preform_file</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">), </span><span class="identifier-syntax">L</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>We simply feed the lines one at a time. Preform is parsed with the same
lexer as is used for Inform itself, but using the following set of characters
as word-breaking punctuation marks:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">PREFORM_PUNCTUATION_MARKS</span><span class="plain-syntax"> </span><span class="identifier-syntax">L</span><span class="string-syntax">"{}[]_^?&amp;\\"</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">LoadPreform::feed_from_Preform_file</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">LoadPreform::feed_from_Preform_file</span></span>:<br/><a href="4-lp.html#SP1">&#167;1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">F</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="constant-syntax">feed_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax"> = </span><a href="3-fds.html#SP2" class="function-link"><span class="function-syntax">Feeds::begin</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">TextFiles::read</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">, </span><a href="4-lp.html#SP2" class="function-link"><span class="function-syntax">LoadPreform::load_helper</span></a><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Unable to open Preform definition"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="3-fds.html#SP2" class="function-link"><span class="function-syntax">Feeds::end</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">id</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">LoadPreform::load_helper</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">item_name</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_file_position</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tfp</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">unused_state</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">item_name</span><span class="plain-syntax">, </span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="3-fds.html#SP3" class="function-link"><span class="function-syntax">Feeds::feed_text_punctuated</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">item_name</span><span class="plain-syntax">, </span><span class="constant-syntax">PREFORM_PUNCTUATION_MARKS</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>It is also possible to load additional Preform declarations from source
text in Inform, and when that happens, the following is called:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">LoadPreform::parse_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">wd</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="3-fds.html#SP3" class="function-link"><span class="function-syntax">Feeds::feed_text_punctuated</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wd</span><span class="plain-syntax">, </span><span class="constant-syntax">PREFORM_PUNCTUATION_MARKS</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="4-lp.html#SP7" class="function-link"><span class="function-syntax">LoadPreform::parse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">primary_Preform_language</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>Either way, then, all that remains is to write <a href="4-lp.html#SP7" class="internal">LoadPreform::parse</a>. But
before we can get to that, we have to create the...
</p>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. Reserved words in Preform. </b>The ideal tool with which to parse Preform definitions would be Preform, but
then how would we define the grammar required? So we will have to do this
by hand, and in particular, we have to define Preform's syntactic punctuation
marks explicitly. These are, in effect, the reserved words of the Preform
notational language. (Note the absence of the <span class="extract"><span class="extract-syntax">==&gt;</span></span> marker: that's stripped
out by <a href="../../../inweb/index.html" class="internal">inweb</a> and never reaches the <span class="extract"><span class="extract-syntax">Syntax.preform</span></span> file.)
</p>
<p class="commentary">The bare letters K and L are snuck in here for convenience. They aren't
actually used by anything in <a href="index.html" class="internal">words</a>, but are used for kind variables in
<a href="../kinds-module/index.html" class="internal">kinds</a>.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">AMPERSAND_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">BACKSLASH_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">CARET_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">COLONCOLONEQUALS_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">QUESTIONMARK_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">QUOTEQUOTE_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SIXDOTS_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">THREEASTERISKS_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">THREEDOTS_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">THREEHASHES_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">UNDERSCORE_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">language_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">internal_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">CAPITAL_K_V</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">CAPITAL_L_V</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">LoadPreform::create_punctuation</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">LoadPreform::create_punctuation</span></span>:<br/>Words Module - <a href="1-wm.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">AMPERSAND_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"&amp;"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">BACKSLASH_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"\\"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CARET_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"^"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">COLONCOLONEQUALS_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">":"</span><span class="plain-syntax"> </span><span class="string-syntax">":="</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">QUESTIONMARK_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"?"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">QUOTEQUOTE_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"\"\""</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">SIXDOTS_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"......"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">THREEASTERISKS_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"***"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">THREEDOTS_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"..."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">THREEHASHES_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"###"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">UNDERSCORE_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"_"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">language_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"language"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"internal"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CAPITAL_K_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"k"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CAPITAL_L_V</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"l"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. Parsing Preform. </b>The syntax of the <span class="extract"><span class="extract-syntax">Syntax.preform</span></span> is, fortunately, very simple. At any given
time, we are parsing definitions for a given natural language <span class="extract"><span class="extract-syntax">L</span></span>: for example,
English.
</p>
<p class="commentary">Note that Preform can contain comments in square brackets; but that the Lexer
has already removed any such.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">LoadPreform::parse</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">LoadPreform::parse</span></span>:<br/><a href="4-lp.html#SP1">&#167;1</a>, <a href="4-lp.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="constant-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">current_natural_language</span><span class="plain-syntax"> = </span><span class="identifier-syntax">L</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">declarations</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_WORDING</span><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">) == </span><span class="identifier-syntax">PARBREAK_V</span><span class="plain-syntax">) </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::last_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) &gt;= </span><span class="identifier-syntax">wn</span><span class="plain-syntax">+1) &amp;&amp; (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">) == </span><span class="identifier-syntax">language_V</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP7_1" class="named-paragraph-link"><span class="named-paragraph">Parse a definition language switch</span><span class="named-paragraph-number">7.1</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::last_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) &gt;= </span><span class="identifier-syntax">wn</span><span class="plain-syntax">+1) &amp;&amp; (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">+1) == </span><span class="identifier-syntax">internal_V</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP7_2" class="named-paragraph-link"><span class="named-paragraph">Parse an internal nonterminal declaration</span><span class="named-paragraph-number">7.2</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::last_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) &gt;= </span><span class="identifier-syntax">wn</span><span class="plain-syntax">+2) &amp;&amp; (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">+1) == </span><span class="identifier-syntax">COLONCOLONEQUALS_V</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP7_3" class="named-paragraph-link"><span class="named-paragraph">Parse a regular nonterminal declaration</span><span class="named-paragraph-number">7.3</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><a href="4-pu.html#SP7" class="function-link"><span class="function-syntax">PreformUtilities::production_error</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"syntax error in Preform declarations"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="4-to.html#SP7" class="function-link"><span class="function-syntax">Optimiser::optimise_counts</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">declarations</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7_1" class="paragraph-anchor"></a><b>&#167;7.1. </b>We either switch to an existing natural language, or create a new one.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse a definition language switch</span><span class="named-paragraph-number">7.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">lname</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">lname</span><span class="plain-syntax">, </span><span class="string-syntax">"%W"</span><span class="plain-syntax">, </span><a href="3-wrd.html#SP5" class="function-link"><span class="function-syntax">Wordings::one_word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">+1));</span>
<span class="plain-syntax"> </span><span class="constant-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PREFORM_LANGUAGE_FROM_NAME_WORDS_CALLBACK</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PREFORM_LANGUAGE_FROM_NAME_WORDS_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">lname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nl</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Missing: %S\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">lname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-pu.html#SP7" class="function-link"><span class="function-syntax">PreformUtilities::production_error</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"tried to define for missing language"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">lname</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_natural_language</span><span class="plain-syntax"> = </span><span class="identifier-syntax">nl</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">++;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP7">&#167;7</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP7_2" class="paragraph-anchor"></a><b>&#167;7.2. </b>Internal declarations appear as single lines in <span class="extract"><span class="extract-syntax">Syntax.preform</span></span>.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse an internal nonterminal declaration</span><span class="named-paragraph-number">7.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax"> = </span><a href="4-nnt.html#SP8" class="function-link"><span class="function-syntax">Nonterminals::find</span></a><span class="plain-syntax">(</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_pl</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="4-pu.html#SP7" class="function-link"><span class="function-syntax">PreformUtilities::production_error</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"nonterminal internal in one definition and regular in another"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">marked_internal</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">declarations</span><span class="plain-syntax">++;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP7">&#167;7</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP7_3" class="paragraph-anchor"></a><b>&#167;7.3. </b>Regular declarations are much longer and continue until the end of the text,
or until we reach a paragraph break. The body of such a declaration is a list
of productions divided by stroke symbols.
</p>
<p class="commentary">Note that an empty production is not recorded: e.g., if there are two consecutive
strokes, the gap between them will not be considered as a production, and the
second stroke will simply be ignored. I suppose this is arguably a syntax error
and could be rejected as such, but it does no harm.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse a regular nonterminal declaration</span><span class="named-paragraph-number">7.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax"> = </span><a href="4-nnt.html#SP8" class="function-link"><span class="function-syntax">Nonterminals::find</span></a><span class="plain-syntax">(</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">marked_internal</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="4-pu.html#SP7" class="function-link"><span class="function-syntax">PreformUtilities::production_error</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"nonterminal internal in one definition and regular in another"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">production_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pl</span><span class="plain-syntax"> = </span><a href="4-lp.html#SP9" class="function-link"><span class="function-syntax">LoadPreform::find_list_for_language</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">current_natural_language</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax"> += </span><span class="constant-syntax">2</span><span class="plain-syntax">; </span><span class="comment-syntax"> advance past the ID word and the </span><span class="extract"><span class="extract-syntax">::=</span></span><span class="comment-syntax"> word</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">pc</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">x</span><span class="plain-syntax"> = </span><span class="identifier-syntax">wn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">x</span><span class="plain-syntax"> &lt;= </span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::last_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) &amp;&amp; (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">) != </span><span class="identifier-syntax">STROKE_V</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">) != </span><span class="identifier-syntax">PARBREAK_V</span><span class="plain-syntax">)) </span><span class="identifier-syntax">x</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">wn</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">x</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">PW</span><span class="plain-syntax"> = </span><a href="3-wrd.html#SP5" class="function-link"><span class="function-syntax">Wordings::new</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">, </span><span class="identifier-syntax">x</span><span class="plain-syntax">-1); </span><span class="identifier-syntax">wn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">x</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-lp.html#SP10" class="function-link"><span class="function-syntax">LoadPreform::add_production</span></a><span class="plain-syntax">(</span><a href="4-lp.html#SP14" class="function-link"><span class="function-syntax">LoadPreform::new_production</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PW</span><span class="plain-syntax">, </span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pc</span><span class="plain-syntax">++), </span><span class="identifier-syntax">pl</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">wn</span><span class="plain-syntax"> &gt; </span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::last_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) || (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">) == </span><span class="identifier-syntax">PARBREAK_V</span><span class="plain-syntax">)) </span><span class="reserved-syntax">break</span><span class="plain-syntax">; </span><span class="comment-syntax"> reached end</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">++; </span><span class="comment-syntax"> advance past the stroke and continue</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">--;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">declarations</span><span class="plain-syntax">++;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP7">&#167;7</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. Production lists. </b>Regular nonterminals are defined by a list of alternative possibilities
divided by vertical stroke characters; these are called "productions", for
reasons going back to computer science history.
</p>
<p class="commentary">However, the same nonterminal can have multiple lists, one for each language
where it's defined: for example, &lt;competitor&gt; could have one English and
one French definition both in memory at the same time. Each would be an
independent <a href="4-lp.html#SP8" class="internal">production_list</a> object.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">production_list</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="constant-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">definition_language</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">production_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">next_pl</span><span class="plain-syntax">; </span><span class="comment-syntax"> in the list of PLs for a NT</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">production</span><span class="plain-syntax"> *</span><span class="identifier-syntax">first_pr</span><span class="plain-syntax">; </span><span class="comment-syntax"> start of linked list of productions</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">match_avinue</span><span class="plain-syntax"> *</span><span class="identifier-syntax">as_avinue</span><span class="plain-syntax">; </span><span class="comment-syntax"> when compiled to a trie rather than for Preform</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">production_list</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure production_list is accessed in 4/to, 4/le, 4/ni, 4/prf, 4/ins, 4/pu and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">production_list</span><span class="plain-syntax"> *</span><span class="function-syntax">LoadPreform::find_list_for_language</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">LoadPreform::find_list_for_language</span></span>:<br/><a href="4-lp.html#SP7_3">&#167;7.3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="constant-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">production_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pl</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_pl</span><span class="plain-syntax">; </span><span class="identifier-syntax">pl</span><span class="plain-syntax">; </span><span class="identifier-syntax">pl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_pl</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">definition_language</span><span class="plain-syntax"> == </span><span class="identifier-syntax">L</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pl</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">production_list</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">definition_language</span><span class="plain-syntax"> = </span><span class="identifier-syntax">L</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_pr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">as_avinue</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP9_1" class="named-paragraph-link"><span class="named-paragraph">Place the new production list within the nonterminal</span><span class="named-paragraph-number">9.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pl</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9_1" class="paragraph-anchor"></a><b>&#167;9.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Place the new production list within the nonterminal</span><span class="named-paragraph-number">9.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_pl</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_pl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pl</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">production_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">first_pl</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">p</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_pl</span><span class="plain-syntax">)) </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_pl</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_pl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pl</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP9">&#167;9</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. </b>It is undeniably clumsy that the linked list of PLs, and also of productions
within each PL, is managed by hand rather than by using <a href="../../../inweb/foundation-module/index.html" class="internal">foundation</a>. But
speed is critical when parsing Inform text from these productions, and we want
to minimise overhead.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">LoadPreform::add_production</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">LoadPreform::add_production</span></span>:<br/><a href="4-lp.html#SP7_3">&#167;7.3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">production</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pr</span><span class="plain-syntax">, </span><span class="reserved-syntax">production_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pl</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_pr</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_pr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pr</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">production</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_pr</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">p</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_pr</span><span class="plain-syntax">)) </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_pr</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_pr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pr</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>&#167;11. Productions and ptokens. </b>So now we reach the production, which encodes a typical "row" of grammar:
for example,
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">no</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;cardinal-number&gt;</span>
</pre>
<p class="commentary">is a production. This is implemented as still another list, of "ptokens" (the
"p" is silent): that example has three ptokens. Note that the stroke sign and
the defined-by sign are not ptokens; they divide up productions, but aren't
part of them.
</p>
<p class="commentary"><a href="4-to.html" class="internal">The Optimiser</a> calculates data on productions just as it does on nonterminals.
For example, it can see that the above can only match a text if it has exactly
3 words, so it sets both <span class="extract"><span class="Preform-extract-syntax">pr_extremes.min_words</span></span> and <span class="extract"><span class="Preform-extract-syntax">pr_extremes.max_words</span></span> to 3. For the meaning
of the remaining data, and for what "struts" are, see <a href="4-to.html" class="internal">The Optimiser</a>: it
only confuses the picture here.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="Preform-constant-syntax">MAX_STRUTS_PER_PRODUCTION</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">10</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">production</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">first_pt</span><span class="plain-syntax">; </span><span class="comment-syntax"> the linked list of ptokens</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">match_number</span><span class="plain-syntax">; </span><span class="comment-syntax"> 0 for </span><span class="extract"><span class="extract-syntax">/a/</span></span><span class="comment-syntax">, 1 for </span><span class="extract"><span class="extract-syntax">/b/</span></span><span class="comment-syntax"> and so on: see </span><a href="4-ap.html" class="internal">About Preform</a>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_ranges</span><span class="plain-syntax">; </span><span class="comment-syntax"> actually one more, since range 0 is reserved</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">production_optimisation_data</span><span class="plain-syntax"> </span><span class="identifier-syntax">opt</span><span class="plain-syntax">; </span><span class="comment-syntax"> see </span><a href="4-to.html" class="internal">The Optimiser</a>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">production_instrumentation_data</span><span class="plain-syntax"> </span><span class="identifier-syntax">ins</span><span class="plain-syntax">; </span><span class="comment-syntax"> see </span><a href="4-ins.html" class="internal">Instrumentation</a>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">production</span><span class="plain-syntax"> *</span><span class="identifier-syntax">next_pr</span><span class="plain-syntax">; </span><span class="comment-syntax"> within its production list</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">production</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure production is accessed in 4/nnt, 4/to, 4/le, 4/ni, 4/prf, 4/ins, 4/pu and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP12" class="paragraph-anchor"></a><b>&#167;12. </b>And at the bottom of God's great chain, the lowly ptoken. Even this can spawn
another list, though: the token <span class="extract"><span class="extract-syntax">fried/green/tomatoes</span></span> is a list of three ptokens
joined by the <span class="extract"><span class="extract-syntax">alternative_ptoken</span></span> links.
</p>
<p class="commentary">There are really only three kinds of ptoken, wildcards, fixed words, and
nonterminals, but it's fractionally quicker to differentiate the sorts of
wildcard here, so we'll actually divide them into five. The remaining wildcard,
the <span class="extract"><span class="extract-syntax">......</span></span> form of <span class="extract"><span class="extract-syntax">...</span></span>, is represented as <span class="extract"><span class="extract-syntax">MULTIPLE_WILDCARD_PTC</span></span> but with
the <span class="extract"><span class="extract-syntax">balanced_wildcard</span></span> flag set.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">SINGLE_WILDCARD_PTC</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">MULTIPLE_WILDCARD_PTC</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">POSSIBLY_EMPTY_WILDCARD_PTC</span><span class="plain-syntax"> </span><span class="constant-syntax">3</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">FIXED_WORD_PTC</span><span class="plain-syntax"> </span><span class="constant-syntax">4</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">NONTERMINAL_PTC</span><span class="plain-syntax"> </span><span class="constant-syntax">5</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> How to parse text against this ptoken</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">ptoken_category</span><span class="plain-syntax">; </span><span class="comment-syntax"> one of the </span><span class="extract"><span class="extract-syntax">*_PTC</span></span><span class="comment-syntax"> values</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">balanced_wildcard</span><span class="plain-syntax">; </span><span class="comment-syntax"> for </span><span class="extract"><span class="extract-syntax">MULTIPLE_WILDCARD_PTC</span></span><span class="comment-syntax"> ptokens: brackets balanced?</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">negated_ptoken</span><span class="plain-syntax">; </span><span class="comment-syntax"> the </span><span class="extract"><span class="extract-syntax">^</span></span><span class="comment-syntax"> modifier applies</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">disallow_unexpected_upper</span><span class="plain-syntax">; </span><span class="comment-syntax"> the </span><span class="extract"><span class="extract-syntax">_</span></span><span class="comment-syntax"> modifier applies</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt_pt</span><span class="plain-syntax">; </span><span class="comment-syntax"> for </span><span class="extract"><span class="extract-syntax">NONTERMINAL_PTC</span></span><span class="comment-syntax"> ptokens</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve_pt</span><span class="plain-syntax">; </span><span class="comment-syntax"> for </span><span class="extract"><span class="extract-syntax">FIXED_WORD_PTC</span></span><span class="comment-syntax"> ptokens</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">alternative_ptoken</span><span class="plain-syntax">; </span><span class="comment-syntax"> linked list of other vocabulary ptokens</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> What results from a successful match against this ptoken</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">result_index</span><span class="plain-syntax">; </span><span class="comment-syntax"> for </span><span class="extract"><span class="extract-syntax">NONTERMINAL_PTC</span></span><span class="comment-syntax"> ptokens: what result number, counting from 1?</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">range_starts</span><span class="plain-syntax">; </span><span class="comment-syntax"> 1, 2, 3, ... if word range 1, 2, 3, ... starts with this</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">range_ends</span><span class="plain-syntax">; </span><span class="comment-syntax"> 1, 2, 3, ... if word range 1, 2, 3, ... ends with this</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">ptoken_optimisation_data</span><span class="plain-syntax"> </span><span class="identifier-syntax">opt</span><span class="plain-syntax">; </span><span class="comment-syntax"> see </span><a href="4-to.html" class="internal">The Optimiser</a>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">ptoken_instrumentation_data</span><span class="plain-syntax"> </span><span class="identifier-syntax">ins</span><span class="plain-syntax">; </span><span class="comment-syntax"> see </span><a href="4-ins.html" class="internal">Instrumentation</a>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">next_pt</span><span class="plain-syntax">; </span><span class="comment-syntax"> within its production list</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure ptoken is accessed in 4/nnt, 4/to, 4/le, 4/ni, 4/prf, 4/ins, 4/pu and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP13" class="paragraph-anchor"></a><b>&#167;13. </b>Each ptoken has a <span class="extract"><span class="extract-syntax">range_starts</span></span> and <span class="extract"><span class="extract-syntax">range_ends</span></span> number. This is either -1,
or marks that the ptoken occurs as the first or last in a range (or both). For
example, in the production
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">make</span><span class="plain-syntax"> ... </span><span class="identifier-syntax">from</span><span class="plain-syntax"> {</span><span class="identifier-syntax">rice</span><span class="plain-syntax"> ... </span><span class="identifier-syntax">onions</span><span class="plain-syntax">} </span><span class="identifier-syntax">and</span><span class="plain-syntax"> </span><span class="identifier-syntax">peppers</span>
</pre>
<p class="commentary">the first <span class="extract"><span class="extract-syntax">...</span></span> ptoken has start and end set to 1; <span class="extract"><span class="extract-syntax">rice</span></span> has start 2; <span class="extract"><span class="extract-syntax">onions</span></span>
has end 2. Note that the second <span class="extract"><span class="extract-syntax">...</span></span>, inside the braces, doesn't start or
end anything; it normally would, but the wider range consumes it.
</p>
<p class="commentary firstcommentary"><a id="SP14" class="paragraph-anchor"></a><b>&#167;14. Reading productions. </b>We read the wording <span class="extract"><span class="extract-syntax">W</span></span> of a production for the nonterminal <span class="extract"><span class="extract-syntax">nt</span></span>, with <span class="extract"><span class="extract-syntax">pc</span></span>
or "production count" being 0 for the first one defined, 1 for the second,
and so on.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">production</span><span class="plain-syntax"> *</span><span class="function-syntax">LoadPreform::new_production</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">LoadPreform::new_production</span></span>:<br/><a href="4-lp.html#SP7_3">&#167;7.3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">pc</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">production</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">production</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">match_number</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pc</span><span class="plain-syntax">; </span><span class="comment-syntax"> "production count": 0 for first in defn, and so on</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_pr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_ranges</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">; </span><span class="comment-syntax"> so that they count from 1; range 0 is unused</span>
<span class="plain-syntax"> </span><a href="4-to.html#SP4" class="function-link"><span class="function-syntax">Optimiser::initialise_production_data</span></a><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">opt</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><a href="4-ins.html#SP5" class="function-link"><span class="function-syntax">Instrumentation::initialise_production_data</span></a><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ins</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">head</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">tail</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP14_1" class="named-paragraph-link"><span class="named-paragraph">Parse the row of production tokens into a linked list of ptokens</span><span class="named-paragraph-number">14.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">head</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pr</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP14_1" class="paragraph-anchor"></a><b>&#167;14.1. </b>So, then, we have to turn a wording like:
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">make</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">from</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{rice</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">onions/shallots}</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">and</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">peppers</span>
</pre>
<p class="commentary">into a sequence of ptokens, setting <span class="extract"><span class="Preform-extract-syntax">head</span></span> to the first and <span class="extract"><span class="Preform-extract-syntax">tail</span></span> to the last.
This particular example will produce two word ranges: one for the initial <span class="extract"><span class="Preform-extract-syntax">...</span></span>,
one for the matter in the braces. Because of that, we need to keep track of
whether we're in braces or not. (Braces cannot be nested.)
</p>
<p class="commentary">The alternative <span class="extract"><span class="Preform-extract-syntax">onions/shallots</span></span> is called a "slashed chain" in the code below.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="Preform-constant-syntax">OUTSIDE_PTBRACE</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">0</span>
<span class="definition-keyword">define</span> <span class="Preform-constant-syntax">ABOUT_TO_OPEN_PTBRACE</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">1</span>
<span class="definition-keyword">define</span> <span class="Preform-constant-syntax">INSIDE_PTBRACE</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">2</span>
</pre>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse the row of production tokens into a linked list of ptokens</span><span class="named-paragraph-number">14.1</span></span><span class="Preform-comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">result_count</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">negation_modifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">, </span><span class="identifier-syntax">lower_case_modifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">unescaped</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bracing_mode</span><span class="plain-syntax"> = </span><span class="constant-syntax">OUTSIDE_PTBRACE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bracing_begins_at</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">token_count</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_WORDING</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">unescaped</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP14_1_1" class="named-paragraph-link"><span class="named-paragraph">Parse the token modifier symbols</span><span class="named-paragraph-number">14.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pt</span><span class="plain-syntax"> = </span><a href="4-lp.html#SP15" class="function-link"><span class="function-syntax">LoadPreform::parse_slashed_chain</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pr</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">unescaped</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pt</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> == </span><span class="constant-syntax">NONTERMINAL_PTC</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP14_1_3" class="named-paragraph-link"><span class="named-paragraph">Assign a result number</span><span class="named-paragraph-number">14.1.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP14_1_2" class="named-paragraph-link"><span class="named-paragraph">Modify the new ptoken according to the current modifier settings</span><span class="named-paragraph-number">14.1.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP14_1_4" class="named-paragraph-link"><span class="named-paragraph">Add the new ptoken to the production</span><span class="named-paragraph-number">14.1.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP14">&#167;14</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP14_1_1" class="paragraph-anchor"></a><b>&#167;14.1.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse the token modifier symbols</span><span class="named-paragraph-number">14.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">) == </span><span class="identifier-syntax">CARET_V</span><span class="plain-syntax">) { </span><span class="identifier-syntax">negation_modifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">continue</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">) == </span><span class="identifier-syntax">UNDERSCORE_V</span><span class="plain-syntax">) { </span><span class="identifier-syntax">lower_case_modifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">continue</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">) == </span><span class="identifier-syntax">BACKSLASH_V</span><span class="plain-syntax">) { </span><span class="identifier-syntax">unescaped</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">; </span><span class="reserved-syntax">continue</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bracing_mode</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">OUTSIDE_PTBRACE:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">) == </span><span class="identifier-syntax">OPENBRACE_V</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">bracing_mode</span><span class="plain-syntax"> = </span><span class="constant-syntax">ABOUT_TO_OPEN_PTBRACE</span><span class="plain-syntax">; </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">INSIDE_PTBRACE:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">) == </span><span class="identifier-syntax">CLOSEBRACE_V</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bracing_begins_at</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP14_1_1_1" class="named-paragraph-link"><span class="named-paragraph">Set a word range to end here</span><span class="named-paragraph-number">14.1.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">bracing_mode</span><span class="plain-syntax"> = </span><span class="constant-syntax">OUTSIDE_PTBRACE</span><span class="plain-syntax">; </span><span class="identifier-syntax">bracing_begins_at</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP14_1">&#167;14.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP14_1_1_1" class="paragraph-anchor"></a><b>&#167;14.1.1.1. </b>A bracing can be followed by <span class="extract"><span class="extract-syntax">? N</span></span> to make it have the number <span class="extract"><span class="extract-syntax">N</span></span>, rather
than the next number counting upwards; see <a href="4-ap.html" class="internal">About Preform</a>.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Set a word range to end here</span><span class="named-paragraph-number">14.1.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rnum</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_ranges</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">i</span><span class="plain-syntax">+2 &lt;= </span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::last_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) &amp;&amp; (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">+1) == </span><span class="identifier-syntax">QUESTIONMARK_V</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="2-vcb.html#SP10" class="function-link"><span class="function-syntax">Vocabulary::test_flags</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">+2, </span><span class="constant-syntax">NUMBER_MC</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">rnum</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP8" class="function-link"><span class="function-syntax">Vocabulary::get_literal_number_value</span></a><span class="plain-syntax">(</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">+2));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> += </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">rnum</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">rnum</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_RANGES_PER_PRODUCTION</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><a href="4-pu.html#SP7" class="function-link"><span class="function-syntax">PreformUtilities::production_error</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pr</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"range number out of range"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">rnum</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">bracing_begins_at</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_starts</span><span class="plain-syntax"> = </span><span class="identifier-syntax">rnum</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tail</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">range_ends</span><span class="plain-syntax"> = </span><span class="identifier-syntax">rnum</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP14_1_1">&#167;14.1.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP14_1_2" class="paragraph-anchor"></a><b>&#167;14.1.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Modify the new ptoken according to the current modifier settings</span><span class="named-paragraph-number">14.1.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">negation_modifier</span><span class="plain-syntax">) </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">negated_ptoken</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">lower_case_modifier</span><span class="plain-syntax">) </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">disallow_unexpected_upper</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">unescaped</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">negation_modifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">lower_case_modifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bracing_mode</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">OUTSIDE_PTBRACE:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> == </span><span class="constant-syntax">SINGLE_WILDCARD_PTC</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> == </span><span class="constant-syntax">MULTIPLE_WILDCARD_PTC</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> == </span><span class="constant-syntax">POSSIBLY_EMPTY_WILDCARD_PTC</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rnum</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_ranges</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">rnum</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">rnum</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_RANGES_PER_PRODUCTION</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><a href="4-pu.html#SP7" class="function-link"><span class="function-syntax">PreformUtilities::production_error</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pr</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"range number out of range"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">rnum</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_starts</span><span class="plain-syntax"> = </span><span class="identifier-syntax">rnum</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_ends</span><span class="plain-syntax"> = </span><span class="identifier-syntax">rnum</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">ABOUT_TO_OPEN_PTBRACE:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">bracing_begins_at</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">bracing_mode</span><span class="plain-syntax"> = </span><span class="constant-syntax">INSIDE_PTBRACE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP14_1">&#167;14.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP14_1_3" class="paragraph-anchor"></a><b>&#167;14.1.3. </b>A nonterminal can be followed by <span class="extract"><span class="extract-syntax">? N</span></span> to make it have result number <span class="extract"><span class="extract-syntax">N</span></span>,
rather than the next number counting upwards; see <a href="4-ap.html" class="internal">About Preform</a>.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Assign a result number</span><span class="named-paragraph-number">14.1.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">result_count</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">MAX_RESULTS_PER_PRODUCTION</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">i</span><span class="plain-syntax">+2 &lt;= </span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::last_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) &amp;&amp; (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">+1) == </span><span class="identifier-syntax">QUESTIONMARK_V</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="2-vcb.html#SP10" class="function-link"><span class="function-syntax">Vocabulary::test_flags</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">+2, </span><span class="constant-syntax">NUMBER_MC</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">result_index</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP8" class="function-link"><span class="function-syntax">Vocabulary::get_literal_number_value</span></a><span class="plain-syntax">(</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">+2));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">result_index</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">result_index</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_RESULTS_PER_PRODUCTION</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><a href="4-pu.html#SP7" class="function-link"><span class="function-syntax">PreformUtilities::production_error</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pr</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"result number out of range"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">result_index</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> += </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">result_index</span><span class="plain-syntax"> = </span><span class="identifier-syntax">result_count</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">result_count</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><a href="4-pu.html#SP7" class="function-link"><span class="function-syntax">PreformUtilities::production_error</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pr</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"too many nonterminals for one production to hold"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP14_1">&#167;14.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP14_1_4" class="paragraph-anchor"></a><b>&#167;14.1.4. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Add the new ptoken to the production</span><span class="named-paragraph-number">14.1.4</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">token_count</span><span class="plain-syntax">++ &lt; </span><span class="constant-syntax">MAX_PTOKENS_PER_PRODUCTION</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">head</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">head</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pt</span><span class="plain-syntax">; </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">tail</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tail</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><a href="4-pu.html#SP7" class="function-link"><span class="function-syntax">PreformUtilities::production_error</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pr</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"too many tokens on production for nonterminal"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP14_1">&#167;14.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP15" class="paragraph-anchor"></a><b>&#167;15. </b>Here we parse what is, to the Lexer, a single word (at word number <span class="extract"><span class="extract-syntax">wn</span></span>),
but which might actually be a row of possibilities divided by slashes:
for example, <span class="extract"><span class="extract-syntax">onions/shallots</span></span>.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="function-syntax">LoadPreform::parse_slashed_chain</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">LoadPreform::parse_slashed_chain</span></span>:<br/><a href="4-lp.html#SP14_1">&#167;14.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="reserved-syntax">production</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pr</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">unescaped</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">AW</span><span class="plain-syntax"> = </span><a href="3-wrd.html#SP5" class="function-link"><span class="function-syntax">Wordings::one_word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP15_1" class="named-paragraph-link"><span class="named-paragraph">Expand the word range if the token text is slashed</span><span class="named-paragraph-number">15.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP15_2" class="named-paragraph-link"><span class="named-paragraph">Parse the word range into a linked list of alternative ptokens</span><span class="named-paragraph-number">15.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP15_1" class="paragraph-anchor"></a><b>&#167;15.1. </b>Should we detect a slash used to indicate alternatives, we have to ask the
Lexer to have another try, but with <span class="extract"><span class="extract-syntax">/</span></span> as a word-breaking character this time.
So, for example, <span class="extract"><span class="extract-syntax">AW</span></span> might then end up as <span class="extract"><span class="extract-syntax">onions</span></span>, <span class="extract"><span class="extract-syntax">/</span></span>, <span class="extract"><span class="extract-syntax">shallots</span></span>.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Expand the word range if the token text is slashed</span><span class="named-paragraph-number">15.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word_raw_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">k</span><span class="plain-syntax">, </span><span class="identifier-syntax">breakme</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">unescaped</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP15_1_1" class="named-paragraph-link"><span class="named-paragraph">Look out for production match numbers</span><span class="named-paragraph-number">15.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">k</span><span class="plain-syntax">=0; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">k</span><span class="plain-syntax">]) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">k</span><span class="plain-syntax">+1]); </span><span class="identifier-syntax">k</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">k</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">k</span><span class="plain-syntax">] == </span><span class="character-syntax">'/'</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">breakme</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">breakme</span><span class="plain-syntax">) </span><span class="identifier-syntax">AW</span><span class="plain-syntax"> = </span><a href="3-fds.html#SP4" class="function-link"><span class="function-syntax">Feeds::feed_C_string_full</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="string-syntax">"/"</span><span class="plain-syntax">); </span><span class="comment-syntax"> break only at slashes</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP15">&#167;15</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP15_1_1" class="paragraph-anchor"></a><b>&#167;15.1.1. </b>Intercept <span class="extract"><span class="extract-syntax">/a/</span></span> to <span class="extract"><span class="extract-syntax">/z/</span></span> and <span class="extract"><span class="extract-syntax">/aa/</span></span> to <span class="extract"><span class="extract-syntax">/zz/</span></span>, which don't make ptokens at
all, but simply change the production's match number.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Look out for production match numbers</span><span class="named-paragraph-number">15.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">p</span><span class="plain-syntax">[0] == </span><span class="character-syntax">'/'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">Characters::islower</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">[1])) &amp;&amp;</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[2] == </span><span class="character-syntax">'/'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[3] == </span><span class="constant-syntax">0</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">match_number</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">[1] - </span><span class="character-syntax">'a'</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="comment-syntax"> i.e., contribute no token</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">p</span><span class="plain-syntax">[0] == </span><span class="character-syntax">'/'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">Characters::islower</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">[1])) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[2] == </span><span class="identifier-syntax">p</span><span class="plain-syntax">[1]) &amp;&amp;</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[3] == </span><span class="character-syntax">'/'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[4] == </span><span class="constant-syntax">0</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">match_number</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">[1] - </span><span class="character-syntax">'a'</span><span class="plain-syntax"> + </span><span class="constant-syntax">26</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="comment-syntax"> i.e., contribute no token</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP15_1">&#167;15.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP15_2" class="paragraph-anchor"></a><b>&#167;15.2. </b>And then we string together the ptokens made into a linked list with links
provided by <span class="extract"><span class="extract-syntax">-&gt;alternative_ptoken</span></span>, and return the head of this list.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse the word range into a linked list of alternative ptokens</span><span class="named-paragraph-number">15.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">alt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><a href="3-wrd.html#SP11" class="function-link"><span class="function-syntax">Wordings::nonempty</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">AW</span><span class="plain-syntax">); </span><span class="identifier-syntax">AW</span><span class="plain-syntax"> = </span><a href="3-wrd.html#SP8" class="function-link"><span class="function-syntax">Wordings::trim_first_word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">AW</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::first_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">AW</span><span class="plain-syntax">)) != </span><span class="identifier-syntax">FORWARDSLASH_V</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">mode</span><span class="plain-syntax"> = </span><span class="identifier-syntax">unescaped</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::length</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">AW</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="identifier-syntax">mode</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">latest</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><a href="4-lp.html#SP16" class="function-link"><span class="function-syntax">LoadPreform::new_ptoken</span></a><span class="plain-syntax">(</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::first_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">AW</span><span class="plain-syntax">)),</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mode</span><span class="plain-syntax">, </span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">match_number</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">alt</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">latest</span><span class="plain-syntax">; </span><span class="comment-syntax"> thus making </span><span class="extract"><span class="extract-syntax">pt</span></span><span class="comment-syntax"> the head</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">alt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">alternative_ptoken</span><span class="plain-syntax"> = </span><span class="identifier-syntax">latest</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">alt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">latest</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP15">&#167;15</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP16" class="paragraph-anchor"></a><b>&#167;16. </b>Finally, then, the bottom-most function here parses what is definitely a
single word into what will definitely be a single ptoken.
</p>
<p class="commentary">In "escaped" mode, where a backslash has made the text literal, it just
becomes a fixed word; otherwise it could be any of the five categories.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="function-syntax">LoadPreform::new_ptoken</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">LoadPreform::new_ptoken</span></span>:<br/><a href="4-lp.html#SP15_2">&#167;15.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">unescaped</span><span class="plain-syntax">, </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">pc</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">ptoken</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP16_1" class="named-paragraph-link"><span class="named-paragraph">Begin with a blank ptoken</span><span class="named-paragraph-number">16.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP7" class="function-link"><span class="function-syntax">Vocabulary::get_exemplar</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">unescaped</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[0] == </span><span class="character-syntax">'&lt;'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">Wide::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-1] == </span><span class="character-syntax">'&gt;'</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP16_2" class="named-paragraph-link"><span class="named-paragraph">This word is a nonterminal name</span><span class="named-paragraph-number">16.2</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-lp.html#SP16_3" class="named-paragraph-link"><span class="named-paragraph">This word is not a nonterminal name</span><span class="named-paragraph-number">16.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP16_1" class="paragraph-anchor"></a><b>&#167;16.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Begin with a blank ptoken</span><span class="named-paragraph-number">16.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> = </span><span class="constant-syntax">FIXED_WORD_PTC</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">balanced_wildcard</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">negated_ptoken</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">disallow_unexpected_upper</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ve_pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nt_pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">alternative_ptoken</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">result_index</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_starts</span><span class="plain-syntax"> = -1; </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_ends</span><span class="plain-syntax"> = -1;</span>
<span class="plain-syntax"> </span><a href="4-to.html#SP6" class="function-link"><span class="function-syntax">Optimiser::initialise_ptoken_data</span></a><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">opt</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><a href="4-ins.html#SP7" class="function-link"><span class="function-syntax">Instrumentation::initialise_ptoken_data</span></a><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ins</span><span class="plain-syntax">));</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP16">&#167;16</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP16_2" class="paragraph-anchor"></a><b>&#167;16.2. </b>If the text refers to a nonterminal which doesn't yet exist, then this
creates it; that's how we deal with forward references. <a href="4-nnt.html#SP8" class="internal">Nonterminals::find</a>
never returns <span class="extract"><span class="extract-syntax">NULL</span></span>.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">This word is a nonterminal name</span><span class="named-paragraph-number">16.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nt_pt</span><span class="plain-syntax"> = </span><a href="4-nnt.html#SP8" class="function-link"><span class="function-syntax">Nonterminals::find</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ve</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> = </span><span class="constant-syntax">NONTERMINAL_PTC</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP16">&#167;16</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP16_3" class="paragraph-anchor"></a><b>&#167;16.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">This word is not a nonterminal name</span><span class="named-paragraph-number">16.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ve_pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ve</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">unescaped</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ve</span><span class="plain-syntax"> == </span><span class="identifier-syntax">SIXDOTS_V</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> = </span><span class="constant-syntax">MULTIPLE_WILDCARD_PTC</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">balanced_wildcard</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ve</span><span class="plain-syntax"> == </span><span class="identifier-syntax">THREEDOTS_V</span><span class="plain-syntax">) </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> = </span><span class="constant-syntax">MULTIPLE_WILDCARD_PTC</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ve</span><span class="plain-syntax"> == </span><span class="identifier-syntax">THREEHASHES_V</span><span class="plain-syntax">) </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> = </span><span class="constant-syntax">SINGLE_WILDCARD_PTC</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ve</span><span class="plain-syntax"> == </span><span class="identifier-syntax">THREEASTERISKS_V</span><span class="plain-syntax">) </span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> = </span><span class="constant-syntax">POSSIBLY_EMPTY_WILDCARD_PTC</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_category</span><span class="plain-syntax"> == </span><span class="constant-syntax">FIXED_WORD_PTC</span><span class="plain-syntax">) </span><a href="4-nnt.html#SP13" class="function-link"><span class="function-syntax">Nonterminals::note_word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pc</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-lp.html#SP16">&#167;16</a>.</li></ul>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="4-nnt.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-ap.html">ap</a></li><li class="progresssection"><a href="4-nnt.html">nnt</a></li><li class="progresscurrent">lp</li><li class="progresssection"><a href="4-to.html">to</a></li><li class="progresssection"><a href="4-le.html">le</a></li><li class="progresssection"><a href="4-ni.html">ni</a></li><li class="progresssection"><a href="4-prf.html">prf</a></li><li class="progresssection"><a href="4-bn.html">bn</a></li><li class="progresssection"><a href="4-ins.html">ins</a></li><li class="progresssection"><a href="4-pu.html">pu</a></li><li class="progressnext"><a href="4-to.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>