1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/indoc/1-cs.html
2020-04-07 01:06:09 +01:00

317 lines
30 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>1/ins</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../compiler.html">compiler tools</a></li>
<li><a href="../other.html"><b>other tools</b></a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul>
<h2>Other Tools</h2>
<ul>
<li><a href="../inblorb/index.html">inblorb</a></li>
<li><a href="../indoc/index.html">indoc</a></li>
<li><a href="../inpolicy/index.html">inpolicy</a></li>
<li><a href="../inrtps/index.html">inrtps</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '1/cs' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../other.html">Other Tools</a></li><li><a href="index.html">indoc</a></li><li><a href="index.html#1">Chapter 1: Setting Up</a></li><li><b>Context Symbols</b></li></ul><p class="purpose">Provides conditional rendering of text, depending on context.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. About symbols</a></li><li><a href="#SP2">&#167;2. Starting up</a></li><li><a href="#SP3">&#167;3. Making and unmaking</a></li><li><a href="#SP4">&#167;4. Testing</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. About symbols. </b>Documentation is allowed to contain rawtext which varies depending on the
context: on what platform it's being written for, or what format it is
being rendered to, for example. The context is defined by which symbol
names have been defined.
</p>
<p class="inwebparagraph">Symbols are C-like identifiers (alphanumeric or underscored). The symbol has
been declared if and only if it is an existing key for the following hash,
and the associated value is "y".
</p>
<pre class="display">
<span class="reserved">dictionary</span><span class="plain"> *</span><span class="identifier">defined_symbols</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. Starting up. </b>The symbol <code class="display"><span class="extract">indoc</span></code> is always defined, so that, in theory, other programs
working on rawtext can distinguish themselves from us (by not defining it).
For example,
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">{^indoc:}You'll probably never see this paragraph.</span>
</pre>
<p class="inwebparagraph">provides rawtext visible only if <code class="display"><span class="extract">indoc</span></code> isn't the renderer.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Symbols::start_up_symbols</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Symbols::declare_symbol</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"indoc"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Symbols::start_up_symbols is used in 1/mn (<a href="1-mn.html#SP1_1">&#167;1.1</a>).</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. Making and unmaking. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Symbols::declare_symbol</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">symbol</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">defined_symbols</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">defined_symbols</span><span class="plain"> = </span><span class="functiontext">Dictionaries::new</span><span class="plain">(10, </span><span class="constant">TRUE</span><span class="plain">);</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">entry</span><span class="plain"> = </span><span class="functiontext">Dictionaries::create_text</span><span class="plain">(</span><span class="identifier">defined_symbols</span><span class="plain">, </span><span class="identifier">symbol</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">entry</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"y"</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SYMBOLS</span><span class="plain">, </span><span class="string">"Declaring &lt;%S&gt;\n"</span><span class="plain">, </span><span class="identifier">symbol</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Symbols::undeclare_symbol</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">symbol</span><span class="plain">) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">entry</span><span class="plain"> = </span><span class="functiontext">Dictionaries::get_text</span><span class="plain">(</span><span class="identifier">defined_symbols</span><span class="plain">, </span><span class="identifier">symbol</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">entry</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">entry</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"n"</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SYMBOLS</span><span class="plain">, </span><span class="string">"Undeclaring &lt;%S&gt;\n"</span><span class="plain">, </span><span class="identifier">symbol</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Symbols::declare_symbol is used in <a href="#SP2">&#167;2</a>, 1/ins (<a href="1-ins.html#SP5">&#167;5</a>, <a href="1-ins.html#SP3_2">&#167;3.2</a>).</p>
<p class="endnote">The function Symbols::undeclare_symbol is used in 1/ins (<a href="1-ins.html#SP5">&#167;5</a>).</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Testing. </b>This returns 1 if the current context matches the condition given, and 0
otherwise.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Symbols::perform_ifdef</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">cond</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0, </span><span class="identifier">L</span><span class="plain">=</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">L</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::is_whitespace</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)) {</span>
<span class="functiontext">Str::delete_nth_character</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">--; </span><span class="identifier">L</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">v</span><span class="plain"> = </span><span class="functiontext">Symbols::perform_ifdef_inner</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SYMBOLS</span><span class="plain">, </span><span class="string">"Ifdef &lt;%S&gt; --&gt; %s\n"</span><span class="plain">, </span><span class="identifier">cond</span><span class="plain">, </span><span class="identifier">v</span><span class="plain">?</span><span class="string">"yes"</span><span class="plain">:</span><span class="string">"no"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">v</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Symbols::perform_ifdef is used in <a href="#SP5_1">&#167;5.1</a>, <a href="#SP5_2">&#167;5.2</a>, <a href="#SP5_3">&#167;5.3</a>, <a href="#SP5_4">&#167;5.4</a>, 2/ss (<a href="2-ss.html#SP6_1">&#167;6.1</a>), 2/rr (<a href="2-rr.html#SP4_1">&#167;4.1</a>, <a href="2-rr.html#SP4_6_1">&#167;4.6.1</a>).</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>There is an expression grammar here, which we apply correctly if the
condition is well-formed; if it"s a mess, we try to return 0, but don"t go
to any trouble to report errors.
</p>
<p class="inwebparagraph">Any condition can be bracketed; otherwise we have the unary operator <code class="display"><span class="extract">^</span></code>
(negation), the binary <code class="display"><span class="extract">+</span></code> (conjunction), and binary <code class="display"><span class="extract">,</span></code> (disjunction),
which associate in that order. An atomic condition is true if and only if
it is a declared symbol. So for example
</p>
<p class="inwebparagraph"> ^alpha,beta+gamma
</p>
<p class="inwebparagraph">is true if either alpha is undeclared, or if both beta and gamma are declared.
Whereas
</p>
<p class="inwebparagraph"> ^(alpha,beta)+gamma
^alpha+^beta+gamma
</p>
<p class="inwebparagraph">are both true if alpha and beta are undeclared but gamma is declared.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Symbols::perform_ifdef_inner</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">cond</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Subexpressions can be bracketed</span> <span class="cwebmacronumber">5.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">The comma operator is left-associative and means or</span> <span class="cwebmacronumber">5.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">The plus operator is left-associative and means and</span> <span class="cwebmacronumber">5.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">The caret operator is unary and means not</span> <span class="cwebmacronumber">5.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">A bare symbol name is true if and only if it is declared</span> <span class="cwebmacronumber">5.5</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">The expression is malformed</span> <span class="cwebmacronumber">5.6</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Symbols::perform_ifdef_inner is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP5_1"></a><b>&#167;5.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Subexpressions can be bracketed</span> <span class="cwebmacronumber">5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">cond</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"%((%c*)%)"</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Symbols::perform_ifdef</span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP5_2"></a><b>&#167;5.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">The comma operator is left-associative and means or</span> <span class="cwebmacronumber">5.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain"> = </span><span class="functiontext">Symbols::find_operator</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">, </span><span class="character">','</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">cond</span><span class="plain">);</span>
<span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">);</span>
<span class="functiontext">Str::copy_tail</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">cond</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">+1);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = ((</span><span class="functiontext">Symbols::perform_ifdef</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">)) || (</span><span class="functiontext">Symbols::perform_ifdef</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)));</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> == -2) </span>&lt;<span class="cwebmacro">The expression is malformed</span> <span class="cwebmacronumber">5.6</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP5_3"></a><b>&#167;5.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">The plus operator is left-associative and means and</span> <span class="cwebmacronumber">5.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain"> = </span><span class="functiontext">Symbols::find_operator</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">, </span><span class="character">'+'</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">cond</span><span class="plain">);</span>
<span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">);</span>
<span class="functiontext">Str::copy_tail</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">cond</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">+1);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = ((</span><span class="functiontext">Symbols::perform_ifdef</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">)) &amp;&amp; (</span><span class="functiontext">Symbols::perform_ifdef</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)));</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> == -2) </span>&lt;<span class="cwebmacro">The expression is malformed</span> <span class="cwebmacronumber">5.6</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP5_4"></a><b>&#167;5.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">The caret operator is unary and means not</span> <span class="cwebmacronumber">5.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">cond</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"%^(%c*)"</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Symbols::perform_ifdef</span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">?</span><span class="identifier">FALSE:TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP5_5"></a><b>&#167;5.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">A bare symbol name is true if and only if it is declared</span> <span class="cwebmacronumber">5.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">cond</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"%i+"</span><span class="plain">)) {</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">entry</span><span class="plain"> = </span><span class="functiontext">Dictionaries::get_text</span><span class="plain">(</span><span class="identifier">defined_symbols</span><span class="plain">, </span><span class="identifier">cond</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">entry</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"y"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP5_6"></a><b>&#167;5.6. </b><code class="display">
&lt;<span class="cwebmacrodefn">The expression is malformed</span> <span class="cwebmacronumber">5.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Errors::with_text</span><span class="plain">(</span><span class="string">"malformed condition: %S"</span><span class="plain">, </span><span class="identifier">cond</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5">&#167;5</a>, <a href="#SP5_2">&#167;5.2</a>, <a href="#SP5_3">&#167;5.3</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>The following looks for a single character <code class="display"><span class="extract">op</span></code> in any unbracketed interior
parts of the text <code class="display"><span class="extract">cond</span></code>, and looks out for mismatched brackets on the way.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Symbols::find_operator</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">cond</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">op</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bl</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">); </span><span class="identifier">k</span><span class="plain"> &lt; </span><span class="identifier">L</span><span class="plain">; </span><span class="identifier">k</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ch</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ch</span><span class="plain"> == </span><span class="character">'('</span><span class="plain">) </span><span class="identifier">bl</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ch</span><span class="plain"> == </span><span class="character">')'</span><span class="plain">) </span><span class="identifier">bl</span><span class="plain">--;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bl</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -2; </span><span class="comment">Too many close brackets</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">bl</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">k</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">k</span><span class="plain"> &lt; </span><span class="identifier">L</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">) &amp;&amp; (</span><span class="identifier">ch</span><span class="plain"> == </span><span class="identifier">op</span><span class="plain">)) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bl</span><span class="plain"> != </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -2; </span><span class="comment">Too many open brackets</span>
<span class="reserved">return</span><span class="plain"> -1; </span><span class="comment">Not found</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Symbols::find_operator is used in <a href="#SP5_2">&#167;5.2</a>, <a href="#SP5_3">&#167;5.3</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="1-ins.html">Back to 'Instructions'</a></li><li><i>(This section ends Chapter 1: Setting Up.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>