144 lines
24 KiB
HTML
144 lines
24 KiB
HTML
<!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">☰</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'>−</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">></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">></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">></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">></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">></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">></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">></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">></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">></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">></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">></span> <span class="ident">IResult</span><span class="op"><</span><span class="ident">I</span>,<span class="ident">O</span><span class="op">></span> <span class="op">|</span> <span class="ident">I</span> <span class="op">-</span><span class="op">></span> <span class="ident">IResult</span><span class="op"><</span><span class="ident">I</span>,<span class="ident">O</span><span class="op">></span> <span class="op">|</span> ... <span class="op">|</span> <span class="ident">I</span> <span class="op">-</span><span class="op">></span> <span class="ident">IResult</span><span class="op"><</span><span class="ident">I</span>,<span class="ident">O</span><span class="op">></span> ) <span class="op">=</span><span class="op">></span> <span class="ident">I</span> <span class="op">-</span><span class="op">></span> <span class="ident">IResult</span><span class="op"><</span><span class="ident">I</span>, <span class="ident">O</span><span class="op">></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 "dragon" or "beast"</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">"dragon"</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">"beast"</span> ) ) );
|
||
|
||
<span class="comment">// Given the input "dragon slayer", the parser will match "dragon"</span>
|
||
<span class="comment">// and the rest will be " slayer"</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"dragon slayer"</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"dragon"</span>);
|
||
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">rest</span>, <span class="string">b" slayer"</span>);
|
||
|
||
<span class="comment">// Given the input "beast of Gevaudan", the parser will match "beast"</span>
|
||
<span class="comment">// and the rest will be " of Gevaudan"</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">&</span><span class="string">b"beast of Gevaudan"</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"beast"</span>);
|
||
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">rest</span>, <span class="string">b" of Gevaudan"</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'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'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">></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 "dragon",</span>
|
||
<span class="comment">// the `Beast` variant when matching "beast" 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's name.</span>
|
||
<span class="macro">named</span><span class="macro">!</span>(<span class="ident">creature</span><span class="op"><</span><span class="ident">Creature</span><span class="op">></span>, <span class="macro">alt</span><span class="macro">!</span>(
|
||
<span class="macro">tag</span><span class="macro">!</span>(<span class="string">"dragon"</span>) <span class="op">=</span><span class="op">></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">"beast"</span>) <span class="op">=</span><span class="op">></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">></span> { <span class="op">|</span><span class="ident">r</span>: <span class="kw-2">&</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 "dragon slayer" the parser will return `Creature::Dragon`</span>
|
||
<span class="comment">// and the rest will be " slayer"</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"dragon slayer"</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" slayer"</span>);
|
||
|
||
<span class="comment">// Given the input "beast of Gevaudan" the parser will return `Creature::Beast`</span>
|
||
<span class="comment">// and the rest will be " of Gevaudan"</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"beast of Gevaudan"</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" of Gevaudan"</span>);
|
||
|
||
<span class="comment">// Given the input "demon hunter" the parser will return `Creature::Unkown(5)`</span>
|
||
<span class="comment">// and the rest will be " hunter"</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"demon hunter"</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" hunter"</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">"abcd"</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">"ef"</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">"ghi"</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">"kl"</span> ) ) );</pre></div>
|
||
<p>With this parser, if you pass <code>"abcd"</code> as input, the first alternative parses it correctly,
|
||
but if you pass <code>"efg"</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">"ef"</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">"kl"</span>) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">"ghi"</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">"abcd"</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">"abcd"</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">"ef"</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">"ghi"</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">"kl"</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">"abcd"</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">"ab"</span> ) <span class="op">|</span> <span class="macro">tag</span><span class="macro">!</span>( <span class="string">"ef"</span> ) ) );</pre></div>
|
||
<p>in that case, if you order by size, passing <code>"abcd"</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">"ab"</span>),
|
||
<span class="macro">alt</span><span class="macro">!</span>(
|
||
<span class="macro">tag</span><span class="macro">!</span>( <span class="string">"cd"</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">"ef"</span> )
|
||
)
|
||
);</pre></div>
|
||
<p><code>preceded!</code> will first parse <code>"ab"</code> then, if successful, try the alternatives "cd",
|
||
or empty input (End Of File). If none of them work, <code>preceded!</code> will fail and
|
||
"ef" 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> |