Files
mercator_service/nom/macro.alt.html

144 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `alt` macro in crate `nom`."><meta name="keywords" content="rust, rustlang, rust-lang, alt"><title>nom::alt - Rust</title><link rel="stylesheet" type="text/css" href="../normalize.css"><link rel="stylesheet" type="text/css" href="../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" type="text/css" href="../dark.css"><link rel="stylesheet" type="text/css" href="../light.css" id="themeStyle"><script src="../storage.js"></script><noscript><link rel="stylesheet" href="../noscript.css"></noscript><link rel="shortcut icon" href="../favicon.ico"><style type="text/css">#crate-search{background-image:url("../down-arrow.svg");}</style></head><body class="rustdoc macro"><!--[if lte IE 8]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="sidebar"><div class="sidebar-menu">&#9776;</div><a href='../nom/index.html'><div class='logo-container'><img src='../rust-logo.png' alt='logo'></div></a><div class="sidebar-elems"><p class='location'><a href='index.html'>nom</a></p><script>window.sidebarCurrent = {name: 'alt', ty: 'macro', relpath: ''};</script><script defer src="sidebar-items.js"></script></div></nav><div class="theme-picker"><button id="theme-picker" aria-label="Pick another theme!"><img src="../brush.svg" width="18" alt="Pick another theme!"></button><div id="theme-choices"></div></div><script src="../theme.js"></script><nav class="sub"><form class="search-form"><div class="search-container"><div><select id="crate-search"><option value="All crates">All crates</option></select><input class="search-input" name="search" disabled autocomplete="off" spellcheck="false" placeholder="Click or press S to search, ? for more options…" type="search"></div><a id="settings-menu" href="../settings.html"><img src="../wheel.svg" width="18" alt="Change settings"></a></div></form></nav><section id="main" class="content"><h1 class='fqn'><span class='out-of-band'><span id='render-detail'><a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">[<span class='inner'>&#x2212;</span>]</a></span><a class='srclink' href='../src/nom/branch.rs.html#169-258' title='goto source code'>[src]</a></span><span class='in-band'>Macro <a href='index.html'>nom</a>::<wbr><a class="macro" href=''>alt</a></span></h1><div class="docblock type-decl hidden-by-usual-hider"><div class="example-wrap"><pre class="rust macro">
<span class="macro">macro_rules</span><span class="macro">!</span> <span class="ident">alt</span> {
(<span class="ident">__impl</span> <span class="macro-nonterminal">$</span><span class="macro-nonterminal">i</span>:<span class="ident">expr</span>, <span class="macro-nonterminal">$</span><span class="macro-nonterminal">submac</span>:<span class="macro">ident</span><span class="macro">!</span>( $(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">args</span>:<span class="ident">tt</span>)<span class="op">*</span> ), $(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">rest</span>:<span class="ident">tt</span>)<span class="op">*</span> ) <span class="op">=</span><span class="op">&gt;</span> { ... };
(<span class="ident">__impl</span> <span class="macro-nonterminal">$</span><span class="macro-nonterminal">i</span>:<span class="ident">expr</span>, <span class="macro-nonterminal">$</span><span class="macro-nonterminal">e</span>:<span class="ident">path</span>, $(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">rest</span>:<span class="ident">tt</span>)<span class="op">*</span> ) <span class="op">=</span><span class="op">&gt;</span> { ... };
(<span class="ident">__impl</span> <span class="macro-nonterminal">$</span><span class="macro-nonterminal">i</span>:<span class="ident">expr</span>, <span class="macro-nonterminal">$</span><span class="macro-nonterminal">e</span>:<span class="ident">path</span> <span class="op">|</span> $(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">rest</span>:<span class="ident">tt</span>)<span class="kw-2">*</span>) <span class="op">=</span><span class="op">&gt;</span> { ... };
(<span class="ident">__impl</span> <span class="macro-nonterminal">$</span><span class="macro-nonterminal">i</span>:<span class="ident">expr</span>, <span class="macro-nonterminal">$</span><span class="macro-nonterminal">subrule</span>:<span class="macro">ident</span><span class="macro">!</span>( $(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">args</span>:<span class="ident">tt</span>)<span class="kw-2">*</span>) <span class="op">|</span> $(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">rest</span>:<span class="ident">tt</span>)<span class="kw-2">*</span>) <span class="op">=</span><span class="op">&gt;</span> { ... };
(<span class="ident">__impl</span> <span class="macro-nonterminal">$</span><span class="macro-nonterminal">i</span>:<span class="ident">expr</span>, <span class="macro-nonterminal">$</span><span class="macro-nonterminal">subrule</span>:<span class="macro">ident</span><span class="macro">!</span>( $(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">args</span>:<span class="ident">tt</span>)<span class="op">*</span> ) <span class="op">=</span><span class="op">&gt;</span> { <span class="macro-nonterminal">$</span><span class="macro-nonterminal">gen</span>:<span class="ident">expr</span> } <span class="op">|</span> $(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">rest</span>:<span class="ident">tt</span>)<span class="kw-2">*</span>) <span class="op">=</span><span class="op">&gt;</span> { ... };
(<span class="ident">__impl</span> <span class="macro-nonterminal">$</span><span class="macro-nonterminal">i</span>:<span class="ident">expr</span>, <span class="macro-nonterminal">$</span><span class="macro-nonterminal">e</span>:<span class="ident">path</span> <span class="op">=</span><span class="op">&gt;</span> { <span class="macro-nonterminal">$</span><span class="macro-nonterminal">gen</span>:<span class="ident">expr</span> } <span class="op">|</span> $(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">rest</span>:<span class="ident">tt</span>)<span class="kw-2">*</span>) <span class="op">=</span><span class="op">&gt;</span> { ... };
(<span class="ident">__impl</span> <span class="macro-nonterminal">$</span><span class="macro-nonterminal">i</span>:<span class="ident">expr</span>, <span class="ident">__end</span>) <span class="op">=</span><span class="op">&gt;</span> { ... };
(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">i</span>:<span class="ident">expr</span>, $(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">rest</span>:<span class="ident">tt</span>)<span class="kw-2">*</span>) <span class="op">=</span><span class="op">&gt;</span> { ... };
}</pre></div>
</div><div class='docblock'><p>Try a list of parsers and return the result of the first successful one</p>
<div class='information'><div class='tooltip ignore'><span class='tooltiptext'>This example is not tested</span></div></div><div class="example-wrap"><pre class="rust rust-example-rendered ignore">
<span class="macro">alt</span><span class="macro">!</span>(<span class="ident">I</span> <span class="op">-</span><span class="op">&gt;</span> <span class="ident">IResult</span><span class="op">&lt;</span><span class="ident">I</span>,<span class="ident">O</span><span class="op">&gt;</span> <span class="op">|</span> <span class="ident">I</span> <span class="op">-</span><span class="op">&gt;</span> <span class="ident">IResult</span><span class="op">&lt;</span><span class="ident">I</span>,<span class="ident">O</span><span class="op">&gt;</span> <span class="op">|</span> ... <span class="op">|</span> <span class="ident">I</span> <span class="op">-</span><span class="op">&gt;</span> <span class="ident">IResult</span><span class="op">&lt;</span><span class="ident">I</span>,<span class="ident">O</span><span class="op">&gt;</span> ) <span class="op">=</span><span class="op">&gt;</span> <span class="ident">I</span> <span class="op">-</span><span class="op">&gt;</span> <span class="ident">IResult</span><span class="op">&lt;</span><span class="ident">I</span>, <span class="ident">O</span><span class="op">&gt;</span></pre></div>
<p>All the parsers must have the same return type.</p>
<p>If one of the parsers returns <code>Incomplete</code>, <code>alt!</code> will return <code>Incomplete</code>, to retry
once you get more input. Note that it is better for performance to know the
minimum size of data you need before you get into <code>alt!</code>.</p>
<p>The <code>alt!</code> combinator is used in the following way:</p>
<div class='information'><div class='tooltip ignore'><span class='tooltiptext'>This example is not tested</span></div></div><div class="example-wrap"><pre class="rust rust-example-rendered ignore">
<span class="macro">alt</span><span class="macro">!</span>(<span class="ident">parser_1</span> <span class="op">|</span> <span class="ident">parser_2</span> <span class="op">|</span> ... <span class="op">|</span> <span class="ident">parser_n</span>)</pre></div>
<h1 id="basic-example" class="section-header"><a href="#basic-example">Basic example</a></h1>
<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="comment">// Create a parser that will match either &quot;dragon&quot; or &quot;beast&quot;</span>
<span class="macro">named</span><span class="macro">!</span>( <span class="ident">dragon_or_beast</span>, <span class="macro">alt</span><span class="macro">!</span>( <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;dragon&quot;</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;beast&quot;</span> ) ) );
<span class="comment">// Given the input &quot;dragon slayer&quot;, the parser will match &quot;dragon&quot;</span>
<span class="comment">// and the rest will be &quot; slayer&quot;</span>
<span class="kw">let</span> (<span class="ident">rest</span>, <span class="ident">result</span>) <span class="op">=</span> <span class="ident">dragon_or_beast</span>(<span class="string">b&quot;dragon slayer&quot;</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">result</span>, <span class="string">b&quot;dragon&quot;</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">rest</span>, <span class="string">b&quot; slayer&quot;</span>);
<span class="comment">// Given the input &quot;beast of Gevaudan&quot;, the parser will match &quot;beast&quot;</span>
<span class="comment">// and the rest will be &quot; of Gevaudan&quot;</span>
<span class="kw">let</span> (<span class="ident">rest</span>, <span class="ident">result</span>) <span class="op">=</span> <span class="ident">dragon_or_beast</span>(<span class="kw-2">&amp;</span><span class="string">b&quot;beast of Gevaudan&quot;</span>[..]).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">result</span>, <span class="string">b&quot;beast&quot;</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">rest</span>, <span class="string">b&quot; of Gevaudan&quot;</span>);</pre></div>
<h1 id="manipulate-results" class="section-header"><a href="#manipulate-results">Manipulate results</a></h1>
<p>There exists another syntax for <code>alt!</code> that gives you the ability to
manipulate the result from each parser:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="comment">// We create an enum to represent our creatures</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>,<span class="ident">PartialEq</span>,<span class="ident">Eq</span>)]</span>
<span class="kw">enum</span> <span class="ident">Creature</span> {
<span class="ident">Dragon</span>,
<span class="ident">Beast</span>,
<span class="ident">Unknown</span>(<span class="ident">usize</span>)
}
<span class="comment">// Let&#39;s make a helper function that returns true when not a space</span>
<span class="comment">// we are required to do this because the `take_while!` macro is limited</span>
<span class="comment">// to idents, so we can&#39;t negate `ìs_space` at the call site</span>
<span class="kw">fn</span> <span class="ident">is_not_space</span>(<span class="ident">c</span>: <span class="ident">u8</span>) <span class="op">-</span><span class="op">&gt;</span> <span class="ident">bool</span> { <span class="op">!</span> <span class="ident">nom</span>::<span class="ident">is_space</span>(<span class="ident">c</span>) }
<span class="comment">// Our parser will return the `Dragon` variant when matching &quot;dragon&quot;,</span>
<span class="comment">// the `Beast` variant when matching &quot;beast&quot; and otherwise it will consume</span>
<span class="comment">// the input until a space is found and return an `Unknown` creature with</span>
<span class="comment">// the size of it&#39;s name.</span>
<span class="macro">named</span><span class="macro">!</span>(<span class="ident">creature</span><span class="op">&lt;</span><span class="ident">Creature</span><span class="op">&gt;</span>, <span class="macro">alt</span><span class="macro">!</span>(
<span class="macro">tag</span><span class="macro">!</span>(<span class="string">&quot;dragon&quot;</span>) <span class="op">=</span><span class="op">&gt;</span> { <span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">Creature</span>::<span class="ident">Dragon</span> } <span class="op">|</span>
<span class="macro">tag</span><span class="macro">!</span>(<span class="string">&quot;beast&quot;</span>) <span class="op">=</span><span class="op">&gt;</span> { <span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">Creature</span>::<span class="ident">Beast</span> } <span class="op">|</span>
<span class="macro">take_while</span><span class="macro">!</span>(<span class="ident">is_not_space</span>) <span class="op">=</span><span class="op">&gt;</span> { <span class="op">|</span><span class="ident">r</span>: <span class="kw-2">&amp;</span>[<span class="ident">u8</span>]<span class="op">|</span> <span class="ident">Creature</span>::<span class="ident">Unknown</span>(<span class="ident">r</span>.<span class="ident">len</span>()) }
<span class="comment">// the closure takes the result as argument if the parser is successful</span>
));
<span class="comment">// Given the input &quot;dragon slayer&quot; the parser will return `Creature::Dragon`</span>
<span class="comment">// and the rest will be &quot; slayer&quot;</span>
<span class="kw">let</span> (<span class="ident">rest</span>, <span class="ident">result</span>) <span class="op">=</span> <span class="ident">creature</span>(<span class="string">b&quot;dragon slayer&quot;</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">result</span>, <span class="ident">Creature</span>::<span class="ident">Dragon</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">rest</span>, <span class="string">b&quot; slayer&quot;</span>);
<span class="comment">// Given the input &quot;beast of Gevaudan&quot; the parser will return `Creature::Beast`</span>
<span class="comment">// and the rest will be &quot; of Gevaudan&quot;</span>
<span class="kw">let</span> (<span class="ident">rest</span>, <span class="ident">result</span>) <span class="op">=</span> <span class="ident">creature</span>(<span class="string">b&quot;beast of Gevaudan&quot;</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">result</span>, <span class="ident">Creature</span>::<span class="ident">Beast</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">rest</span>, <span class="string">b&quot; of Gevaudan&quot;</span>);
<span class="comment">// Given the input &quot;demon hunter&quot; the parser will return `Creature::Unkown(5)`</span>
<span class="comment">// and the rest will be &quot; hunter&quot;</span>
<span class="kw">let</span> (<span class="ident">rest</span>, <span class="ident">result</span>) <span class="op">=</span> <span class="ident">creature</span>(<span class="string">b&quot;demon hunter&quot;</span>).<span class="ident">unwrap</span>();
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">result</span>, <span class="ident">Creature</span>::<span class="ident">Unknown</span>(<span class="number">5</span>));
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">rest</span>, <span class="string">b&quot; hunter&quot;</span>);</pre></div>
<h1 id="behaviour-of-alt" class="section-header"><a href="#behaviour-of-alt">Behaviour of <code>alt!</code></a></h1>
<p><strong>BE CAREFUL</strong> there is a case where the behaviour of <code>alt!</code> can be confusing:</p>
<p>when the alternatives have different lengths, like this case:</p>
<div class='information'><div class='tooltip ignore'><span class='tooltiptext'>This example is not tested</span></div></div><div class="example-wrap"><pre class="rust rust-example-rendered ignore">
<span class="macro">named</span><span class="macro">!</span>( <span class="ident">test</span>, <span class="macro">alt</span><span class="macro">!</span>( <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;abcd&quot;</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;ef&quot;</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;ghi&quot;</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;kl&quot;</span> ) ) );</pre></div>
<p>With this parser, if you pass <code>&quot;abcd&quot;</code> as input, the first alternative parses it correctly,
but if you pass <code>&quot;efg&quot;</code>, the first alternative will return <code>Incomplete</code>, since it needs an input
of 4 bytes. This behaviour of <code>alt!</code> is expected: if you get a partial input that isn't matched
by the first alternative, but would match if the input was complete, you want <code>alt!</code> to indicate
that it cannot decide with limited information.</p>
<p>There are two ways to fix this behaviour. The first one consists in ordering the alternatives
by size, like this:</p>
<div class='information'><div class='tooltip ignore'><span class='tooltiptext'>This example is not tested</span></div></div><div class="example-wrap"><pre class="rust rust-example-rendered ignore">
<span class="macro">named</span><span class="macro">!</span>( <span class="ident">test</span>, <span class="macro">alt</span><span class="macro">!</span>( <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;ef&quot;</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;kl&quot;</span>) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;ghi&quot;</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;abcd&quot;</span> ) ) );</pre></div>
<p>With this solution, the largest alternative will be tested last.</p>
<p>The other solution uses the <code>complete!</code> combinator, which transforms an <code>Incomplete</code> in an
<code>Error</code>. If one of the alternatives returns <code>Incomplete</code> but is wrapped by <code>complete!</code>,
<code>alt!</code> will try the next alternative. This is useful when you know that
you will not get partial input:</p>
<div class='information'><div class='tooltip ignore'><span class='tooltiptext'>This example is not tested</span></div></div><div class="example-wrap"><pre class="rust rust-example-rendered ignore">
<span class="macro">named</span><span class="macro">!</span>( <span class="ident">test</span>,
<span class="macro">alt</span><span class="macro">!</span>(
<span class="macro">complete</span><span class="macro">!</span>( <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;abcd&quot;</span> ) ) <span class="op">|</span>
<span class="macro">complete</span><span class="macro">!</span>( <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;ef&quot;</span> ) ) <span class="op">|</span>
<span class="macro">complete</span><span class="macro">!</span>( <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;ghi&quot;</span> ) ) <span class="op">|</span>
<span class="macro">complete</span><span class="macro">!</span>( <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;kl&quot;</span> ) )
)
);</pre></div>
<p>If you want the <code>complete!</code> combinator to be applied to all rules then use the convenience
<code>alt_complete!</code> macro (see below).</p>
<p>This behaviour of <code>alt!</code> can get especially confusing if multiple alternatives have different
sizes but a common prefix, like this:</p>
<div class='information'><div class='tooltip ignore'><span class='tooltiptext'>This example is not tested</span></div></div><div class="example-wrap"><pre class="rust rust-example-rendered ignore">
<span class="macro">named</span><span class="macro">!</span>( <span class="ident">test</span>, <span class="macro">alt</span><span class="macro">!</span>( <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;abcd&quot;</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;ab&quot;</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;ef&quot;</span> ) ) );</pre></div>
<p>in that case, if you order by size, passing <code>&quot;abcd&quot;</code> as input will always be matched by the
smallest parser, so the solution using <code>complete!</code> is better suited.</p>
<p>You can also nest multiple <code>alt!</code>, like this:</p>
<div class='information'><div class='tooltip ignore'><span class='tooltiptext'>This example is not tested</span></div></div><div class="example-wrap"><pre class="rust rust-example-rendered ignore">
<span class="macro">named</span><span class="macro">!</span>( <span class="ident">test</span>,
<span class="macro">alt</span><span class="macro">!</span>(
<span class="macro">preceded</span><span class="macro">!</span>(
<span class="macro">tag</span><span class="macro">!</span>(<span class="string">&quot;ab&quot;</span>),
<span class="macro">alt</span><span class="macro">!</span>(
<span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;cd&quot;</span> ) <span class="op">|</span>
<span class="macro">eof</span><span class="macro">!</span>()
)
)
<span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">&quot;ef&quot;</span> )
)
);</pre></div>
<p><code>preceded!</code> will first parse <code>&quot;ab&quot;</code> then, if successful, try the alternatives &quot;cd&quot;,
or empty input (End Of File). If none of them work, <code>preceded!</code> will fail and
&quot;ef&quot; will be tested.</p>
</div></section><section id="search" class="content hidden"></section><section class="footer"></section><script>window.rootPath = "../";window.currentCrate = "nom";</script><script src="../aliases.js"></script><script src="../main.js"></script><script defer src="../search-index.js"></script></body></html>