1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 08:34:22 +03:00
inform7/docs/words-module/4-to.html
2022-04-28 17:37:28 +01:00

361 lines
54 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>The Optimiser</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
MathJax = {
tex: {
inlineMath: '$', '$'], ['\\(', '\\)'
},
svg: {
fontCache: 'global'
}
};
</script>
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Preform-Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../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 'The Optimiser' 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>The Optimiser</b></li></ul></div>
<p class="purpose">To precalculate data which enables rapid parsing of source text against a Preform grammar.</p>
<ul class="toc"><li><a href="4-to.html#SP1">&#167;1. Nonterminal optimisation data</a></li><li><a href="4-to.html#SP3">&#167;3. Production optimisation data</a></li><li><a href="4-to.html#SP5">&#167;5. Ptoken optimisation data</a></li><li><a href="4-to.html#SP7">&#167;7. Optimising nonterminals</a></li><li><a href="4-to.html#SP9">&#167;9. Width and elasticity</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Nonterminal optimisation data. </b>Nonterminals, productions and even ptokens all have packets of precalculated
optimisation data attached.
</p>
<p class="commentary">To begin with, NTs. <span class="extract"><span class="extract-syntax">nt_ntic</span></span> is the "NTI constraint", imposing conditions
which any matching range of words must conform to: see <a href="4-ni.html" class="internal">Nonterminal Incidences</a>.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal_optimisation_data</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">optimised_in_this_pass</span><span class="plain-syntax">; </span><span class="comment-syntax"> have the following been worked out yet?</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">length_extremes</span><span class="plain-syntax"> </span><span class="identifier-syntax">nt_extremes</span><span class="plain-syntax">; </span><span class="comment-syntax"> for any wording matching this</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">nt_incidence_bit</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">nti_constraint</span><span class="plain-syntax"> </span><span class="identifier-syntax">nt_ntic</span><span class="plain-syntax">;</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">nonterminal_optimisation_data</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure nonterminal_optimisation_data is accessed in 4/nnt, 4/le, 4/ni, 4/prf, 4/ins and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </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">Optimiser::initialise_nonterminal_data</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Optimiser::initialise_nonterminal_data</span></span>:<br/>Nonterminals - <a href="4-nnt.html#SP8">&#167;8</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">nonterminal_optimisation_data</span><span class="plain-syntax"> *</span><span class="identifier-syntax">opt</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">opt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">optimised_in_this_pass</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">opt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nt_extremes</span><span class="plain-syntax"> = </span><a href="4-le.html#SP4" class="function-link"><span class="function-syntax">LengthExtremes::at_least_one_word</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">opt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nt_incidence_bit</span><span class="plain-syntax"> = -1; </span><span class="comment-syntax"> meaning "not yet allocated"</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">opt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nt_ntic</span><span class="plain-syntax"> = </span><a href="4-ni.html#SP9" class="function-link"><span class="function-syntax">NTI::unconstrained</span></a><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. Production optimisation data. </b>Like nonterminals, productions have minimum and maximum word counts, and an
NTI constraint:
</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_optimisation_data</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">length_extremes</span><span class="plain-syntax"> </span><span class="identifier-syntax">pr_extremes</span><span class="plain-syntax">; </span><span class="comment-syntax"> for any wording matching this</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">nti_constraint</span><span class="plain-syntax"> </span><span class="identifier-syntax">pr_ntic</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">no_struts</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">struts</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_STRUTS_PER_PRODUCTION</span><span class="plain-syntax">]; </span><span class="comment-syntax"> first ptoken in strut</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">strut_lengths</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_STRUTS_PER_PRODUCTION</span><span class="plain-syntax">]; </span><span class="comment-syntax"> length of the strut in words</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">production_optimisation_data</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure production_optimisation_data is accessed in 4/le, 4/ni, 4/prf, 4/ins and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>There's a new idea here as well, though: struts. A "strut" is a run of
ptokens in the interior of the production whose position relative to the
ends is not known. For example, if we match:
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">frogs</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">like</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">but</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">not</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">to</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">eat</span>
</pre>
<p class="commentary">then we know that in a successful match, "frogs" and "like" must be the
first two words in the text matched, and "eat" and "to" the last two.
They are said to have positions 1, 2, -1 and -2 respectively: a positive
number is relative to the start of the range, a negative relative to the end,
so that position 1 is always the first word and position -1 is the last.
</p>
<p class="commentary">But we don't know where "but not" will occur; it could be anywhere in the
middle of the text. The ptokens for such words have position set to 0. A run
of these ptokens, not counting wildcards like <span class="extract"><span class="Preform-extract-syntax">...</span></span>, is called a "strut":
here, then, <span class="extract"><span class="Preform-extract-syntax">but not</span></span> is a strut. We can think of it as a partition which
can slide backwards and forwards. This strut has length 2, not because it
contains two ptokens, but because it is always two words wide.
</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">Optimiser::initialise_production_data</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">Optimiser::initialise_production_data</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP14">&#167;14</a></span></button><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="plain-syntax"> </span><span class="identifier-syntax">opt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_struts</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">opt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">pr_extremes</span><span class="plain-syntax"> = </span><a href="4-le.html#SP4" class="function-link"><span class="function-syntax">LengthExtremes::at_least_one_word</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">opt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">pr_ntic</span><span class="plain-syntax"> = </span><a href="4-ni.html#SP9" class="function-link"><span class="function-syntax">NTI::unconstrained</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. Ptoken optimisation data. </b>A ptoken is marked with its position relative to the range matching its
production (see above for positions); with the number of the strut it belongs
to, if it does; and with a <span class="extract"><span class="extract-syntax">ptoken_is_fast</span></span> flag, which is set if the token is
a single fixed word at a known position which is not an endpoint of a bracing.
That sounds a tall order, but in practice many ptokens are indeed fast.
</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">ptoken_optimisation_data</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">ptoken_position</span><span class="plain-syntax">; </span><span class="comment-syntax"> fixed position in range: 1, 2, ... for left, -1, -2, ... for right</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">strut_number</span><span class="plain-syntax">; </span><span class="comment-syntax"> if this is part of a strut, what number? or -1 if not</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">ptoken_is_fast</span><span class="plain-syntax">; </span><span class="comment-syntax"> can be checked in the fast pass of the parser</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">ptoken_optimisation_data</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure ptoken_optimisation_data is accessed in 4/prf, 4/ins and here.</li></ul>
<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">Optimiser::initialise_ptoken_data</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">Optimiser::initialise_ptoken_data</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP16_1">&#167;16.1</a></span></button><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="plain-syntax"> </span><span class="identifier-syntax">opt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_position</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">opt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">strut_number</span><span class="plain-syntax"> = -1;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">opt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ptoken_is_fast</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. Optimising nonterminals. </b>That's enough groundwork laid: we now have to calculate all of these NTIs
and range requirements. The process will have to repeated if there are ever
extra Preform nonterminals created, because new grammar throws off the old
results. So the following may in principle be called multiple times.
</p>
<p class="commentary">Two callback functions have a one-time opportunity to tweak the process.
</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">Optimiser::optimise_counts</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">Optimiser::optimise_counts</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax">) </span><a href="4-to.html#SP7" class="function-link"><span class="function-syntax">Optimiser::clear_requirement_and_extremes</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-ni.html#SP28" class="function-link"><span class="function-syntax">NTI::ask_parent_to_add_constraints</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax">) </span><a href="4-to.html#SP8" class="function-link"><span class="function-syntax">Optimiser::optimise_nonterminal</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax">) </span><a href="4-ni.html#SP24" class="function-link"><span class="function-syntax">NTI::simplify_nt</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Optimiser::clear_requirement_and_extremes</span><span class="plain-syntax">(</span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">opt</span><span class="plain-syntax">.</span><span class="element-syntax">nt_ntic</span><span class="plain-syntax"> = </span><a href="4-ni.html#SP9" class="function-link"><span class="function-syntax">NTI::unconstrained</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">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><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">opt</span><span class="plain-syntax">.</span><span class="element-syntax">optimised_in_this_pass</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">else</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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">optimised_in_this_pass</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">opt</span><span class="plain-syntax">.</span><span class="element-syntax">nt_extremes</span><span class="plain-syntax"> = </span><a href="4-le.html#SP4" class="function-link"><span class="function-syntax">LengthExtremes::at_least_one_word</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. </b>Although it's not obvious from here, the following function is recursive,
because it calls <a href="4-ni.html#SP25" class="internal">NTI::calculate_constraint</a>, and that in turn needs all the
nonterminals in the grammar for <span class="extract"><span class="extract-syntax">nt</span></span> to have been optimised already &mdash; to
ensure which, it calls <a href="4-to.html#SP8" class="internal">Optimiser::optimise_nonterminal</a>. A similar thing
also happens in <a href="4-le.html#SP8" class="internal">LengthExtremes::calculate_for_nt</a>.
</p>
<p class="commentary">Since we cannot rely on grammar to be well-founded, we rig the function to
ensure that a second call to it on the same nonterminal returns immediately;
there are only finitely many NTs and hangs are therefore impossible.
</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">Optimiser::optimise_nonterminal</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">Optimiser::optimise_nonterminal</span></span>:<br/><a href="4-to.html#SP7">&#167;7</a><br/>Length Extremes - <a href="4-le.html#SP9">&#167;9</a><br/>Nonterminal Incidences - <a href="4-ni.html#SP25_2_1_1">&#167;25.2.1.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="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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">optimised_in_this_pass</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">optimised_in_this_pass</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">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">opt</span><span class="plain-syntax">.</span><span class="element-syntax">nt_extremes</span><span class="plain-syntax"> = </span><a href="4-le.html#SP8" class="function-link"><span class="function-syntax">LengthExtremes::calculate_for_nt</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</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="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">for</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">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="identifier-syntax">pr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_pr</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="4-to.html#SP8" class="function-link"><span class="function-syntax">Optimiser::optimise_production</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pr</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-ni.html#SP25" class="function-link"><span class="function-syntax">NTI::calculate_constraint</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Optimiser::optimise_production</span><span class="plain-syntax">(</span><span class="reserved-syntax">production</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pr</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">last</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="comment-syntax"> this will point to the last ptoken in the production</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-to.html#SP8_1" class="named-paragraph-link"><span class="named-paragraph">Compute front-end ptoken positions</span><span class="named-paragraph-number">8.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-to.html#SP8_2" class="named-paragraph-link"><span class="named-paragraph">Compute back-end ptoken positions</span><span class="named-paragraph-number">8.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-to.html#SP8_3" class="named-paragraph-link"><span class="named-paragraph">Compute struts within the production</span><span class="named-paragraph-number">8.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-to.html#SP8_4" class="named-paragraph-link"><span class="named-paragraph">Work out which ptokens are fast</span><span class="named-paragraph-number">8.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8_1" class="paragraph-anchor"></a><b>&#167;8.1. </b>A token is "elastic" if it can match text of differing lengths, and
"inelastic" otherwise. For example, in English, &lt;indefinite-article&gt; is
elastic (it always matches a single word). If the first ptoken is inelastic,
we know it must match words 1 to \(L_1\) of whatever text is to be matched,
and we give it position 1; if the second is also inelastic, that will match
\(L_1+1\) to \(L_2\), and it gets position \(L_1+1\); and so on. As soon as we
hit an elastic token &mdash; a wildcard like <span class="extract"><span class="extract-syntax">...</span></span>, for example &mdash; this
predictability stops, and we can only assign position 0, which means that
we don't know.
</p>
<p class="commentary">Note that we only assign a nonzero position if we know where the ptoken both
starts and finishes; it's not enough just to know where it starts.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compute front-end ptoken positions</span><span class="named-paragraph-number">8.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">posn</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">ptoken</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">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pt</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">pt</span><span class="plain-syntax">; </span><span class="identifier-syntax">pt</span><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="plain-syntax"> </span><span class="identifier-syntax">last</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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><a href="4-to.html#SP9" class="function-link"><span class="function-syntax">Optimiser::ptoken_width</span></a><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">posn</span><span class="plain-syntax"> != </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">L</span><span class="plain-syntax"> != </span><span class="constant-syntax">PTOKEN_ELASTIC</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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">ptoken_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">posn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">posn</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">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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">ptoken_position</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax"> thus clearing any expired positions from earlier</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">posn</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-to.html#SP8">&#167;8</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP8_2" class="paragraph-anchor"></a><b>&#167;8.2. </b>And similarly from the back end, if there are inelastic ptokens at the end
of the production (and which are separated from the front end by at least one
elastic one).
</p>
<p class="commentary">The following has quadratic running time in the number of tokens in the
production, but this is never larger than about 10.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compute back-end ptoken positions</span><span class="named-paragraph-number">8.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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">posn</span><span class="plain-syntax"> = -1;</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="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">last</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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">ptoken_position</span><span class="plain-syntax"> != </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">break</span><span class="plain-syntax">; </span><span class="comment-syntax"> don't use a back-end position if there's a front one</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><a href="4-to.html#SP9" class="function-link"><span class="function-syntax">Optimiser::ptoken_width</span></a><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">posn</span><span class="plain-syntax"> != </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">L</span><span class="plain-syntax"> != </span><span class="constant-syntax">PTOKEN_ELASTIC</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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">ptoken_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">posn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">posn</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">else</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">ptoken</span><span class="plain-syntax"> *</span><span class="identifier-syntax">prevt</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><span class="identifier-syntax">prevt</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">prevt</span><span class="plain-syntax">; </span><span class="identifier-syntax">prevt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">prevt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_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">prevt</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="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">prevt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-to.html#SP8">&#167;8</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP8_3" class="paragraph-anchor"></a><b>&#167;8.3. </b>So, then, a strut is a maximal sequence of one or more inelastic ptokens
each of which has no known position. (Clearly if one of them has a known
position then all of them have, but we're in no hurry so we don't exploit that.)
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compute struts within the production</span><span class="named-paragraph-number">8.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">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">opt</span><span class="plain-syntax">.</span><span class="element-syntax">no_struts</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">ptoken</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">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pt</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">pt</span><span class="plain-syntax">; </span><span class="identifier-syntax">pt</span><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="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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">ptoken_position</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="4-to.html#SP9" class="function-link"><span class="function-syntax">Optimiser::ptoken_width</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pt</span><span class="plain-syntax">) != </span><span class="constant-syntax">PTOKEN_ELASTIC</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">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">opt</span><span class="plain-syntax">.</span><span class="element-syntax">no_struts</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_STRUTS_PER_PRODUCTION</span><span class="plain-syntax">) </span><span class="reserved-syntax">continue</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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">struts</span><span class="plain-syntax">[</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="element-syntax">no_struts</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">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">opt</span><span class="plain-syntax">.</span><span class="element-syntax">strut_lengths</span><span class="plain-syntax">[</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="element-syntax">no_struts</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">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">opt</span><span class="plain-syntax">.</span><span class="element-syntax">ptoken_position</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="4-to.html#SP9" class="function-link"><span class="function-syntax">Optimiser::ptoken_width</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pt</span><span class="plain-syntax">) != </span><span class="constant-syntax">PTOKEN_ELASTIC</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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">strut_number</span><span class="plain-syntax"> = </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="element-syntax">no_struts</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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">strut_lengths</span><span class="plain-syntax">[</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="element-syntax">no_struts</span><span class="plain-syntax">] += </span><a href="4-to.html#SP9" class="function-link"><span class="function-syntax">Optimiser::ptoken_width</span></a><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">next_pt</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">break</span><span class="plain-syntax">; </span><span class="comment-syntax"> should be impossible</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><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="plain-syntax"> }</span>
<span class="plain-syntax"> </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="element-syntax">no_struts</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-to.html#SP8">&#167;8</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP8_4" class="paragraph-anchor"></a><b>&#167;8.4. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Work out which ptokens are fast</span><span class="named-paragraph-number">8.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">ptoken</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">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pt</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">pt</span><span class="plain-syntax">; </span><span class="identifier-syntax">pt</span><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="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">) &amp;&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="element-syntax">ptoken_position</span><span class="plain-syntax"> != </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> &amp;&amp; (</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_starts</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">pt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_ends</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">opt</span><span class="plain-syntax">.</span><span class="element-syntax">ptoken_is_fast</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-to.html#SP8">&#167;8</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. Width and elasticity. </b>If the min and max are the same, that's the width of the ptoken, and if not
then it is said to be "elastic" and has no width as such.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">PTOKEN_ELASTIC</span><span class="plain-syntax"> -1</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Optimiser::ptoken_width</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">Optimiser::ptoken_width</span></span>:<br/><a href="4-to.html#SP8_1">&#167;8.1</a>, <a href="4-to.html#SP8_2">&#167;8.2</a>, <a href="4-to.html#SP8_3">&#167;8.3</a><br/>Preform - <a href="4-prf.html#SP1_3_2_1_4_4_2_3_1_3_1">&#167;1.3.2.1.4.4.2.3.1.3.1</a></span></button><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="plain-syntax"> </span><span class="reserved-syntax">length_extremes</span><span class="plain-syntax"> </span><span class="identifier-syntax">E</span><span class="plain-syntax"> = </span><a href="4-le.html#SP9" class="function-link"><span class="function-syntax">LengthExtremes::calculate_for_pt</span></a><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">E</span><span class="plain-syntax">.</span><span class="identifier-syntax">min_words</span><span class="plain-syntax"> != </span><span class="identifier-syntax">E</span><span class="plain-syntax">.</span><span class="identifier-syntax">max_words</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">PTOKEN_ELASTIC</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">E</span><span class="plain-syntax">.</span><span class="element-syntax">min_words</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="4-lp.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-ap.html">ap</a></li><li class="progresssection"><a href="4-nnt.html">nnt</a></li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresscurrent">to</li><li class="progresssection"><a href="4-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-le.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>