2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-23 17:52:15 +00:00
Files
parser/doc/html/boost_parser/tutorial/a_trivial_example.html
2024-10-03 20:09:21 -05:00

150 lines
14 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>A Trivial Example</title>
<link rel="stylesheet" href="../../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter 1. Boost.Parser">
<link rel="up" href="../tutorial.html" title="Tutorial">
<link rel="prev" href="hello__whomever.html" title="Hello, Whomever">
<link rel="next" href="a_trivial_example_that_gracefully_handles_whitespace.html" title="A Trivial Example That Gracefully Handles Whitespace">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="spirit-nav">
<a accesskey="p" href="hello__whomever.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="a_trivial_example_that_gracefully_handles_whitespace.html"><img src="../../images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_parser.tutorial.a_trivial_example"></a><a class="link" href="a_trivial_example.html" title="A Trivial Example">A Trivial Example</a>
</h3></div></div></div>
<p>
Let's look at a slightly more complicated example, even if it is still trivial.
Instead of taking any old <code class="computeroutput"><span class="keyword">char</span></code>s
we're given, let's require some structure. Let's parse one or more <code class="computeroutput"><span class="keyword">double</span></code>s, separated by commas.
</p>
<p>
The Boost.Parser parser for <code class="computeroutput"><span class="keyword">double</span></code>
is <code class="computeroutput"><a class="link" href="../../boost/parser/double_.html" title="Global double_">double_</a></code>.
So, to parse a single <code class="computeroutput"><span class="keyword">double</span></code>,
we'd just use that. If we wanted to parse two <code class="computeroutput"><span class="keyword">double</span></code>s
in a row, we'd use:
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">double_</span> <span class="special">&gt;&gt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">double_</span>
</pre>
<p>
<code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;</span></code>
in this expression is the sequence-operator; read it as "followed by".
If we combine the sequence-operator with <a href="https://en.wikipedia.org/wiki/Kleene_star" target="_top">Kleene
star</a>, we can get the parser we want by writing:
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">double_</span> <span class="special">&gt;&gt;</span> <span class="special">*(</span><span class="char">','</span> <span class="special">&gt;&gt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">double_</span><span class="special">)</span>
</pre>
<p>
This is a parser that matches at least one <code class="computeroutput"><span class="keyword">double</span></code>
— because of the first <code class="computeroutput"><a class="link" href="../../boost/parser/double_.html" title="Global double_">double_</a></code> in the expression
above — followed by zero or more instances of a-comma-followed-by-a-<code class="computeroutput"><span class="keyword">double</span></code>. Notice that we can use <code class="computeroutput"><span class="char">','</span></code> directly. Though it is not a parser, <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;</span></code>
and the other operators defined on Boost.Parser parsers have overloads that
accept character/parser pairs of arguments; these operator overloads will
create the right parser to recognize <code class="computeroutput"><span class="char">','</span></code>.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">parser</span><span class="special">/</span><span class="identifier">parser</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">string</span><span class="special">&gt;</span>
<span class="keyword">namespace</span> <span class="identifier">bp</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">parser</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"Enter a list of doubles, separated by commas. No pressure. "</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">input</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">getline</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">cin</span><span class="special">,</span> <span class="identifier">input</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">parse</span><span class="special">(</span><span class="identifier">input</span><span class="special">,</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">double_</span> <span class="special">&gt;&gt;</span> <span class="special">*(</span><span class="char">','</span> <span class="special">&gt;&gt;</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">double_</span><span class="special">));</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">result</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"Great! It looks like you entered:\n"</span><span class="special">;</span>
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">double</span> <span class="identifier">x</span> <span class="special">:</span> <span class="special">*</span><span class="identifier">result</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">x</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span>
<span class="special">&lt;&lt;</span> <span class="string">"Good job! Please proceed to the recovery annex for cake.\n"</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
The first example filled in an out-parameter to deliver the result of the
parse. This call to <code class="computeroutput"><a class="link" href="../../boost/parser/parse_id2.html" title="Function template parse">parse()</a></code>
returns a result instead. As you can see, the result is contextually convertible
to <code class="computeroutput"><span class="keyword">bool</span></code>, and <code class="computeroutput"><span class="special">*</span><span class="identifier">result</span></code> is some sort of range. In fact,
the return type of this call to <code class="computeroutput"><a class="link" href="../../boost/parser/parse_id2.html" title="Function template parse">parse()</a></code>
is <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;&gt;</span></code>. Naturally, if the parse fails,
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">nullopt</span></code> is returned. We'll look at how
Boost.Parser maps the type of the parser to the return type, or the filled
in out-parameter's type, a bit later.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
There's a type trait that can tell you the attribute type for a parser,
<code class="computeroutput"><a class="link" href="../../boost/parser/attribute.html" title="Struct template attribute">attribute</a></code>
(and an associated alias <code class="computeroutput"><a class="link" href="../../boost/parser/attribute_t.html" title="Type definition attribute_t">attribute_t</a></code>). We'll discuss
it more in the <a class="link" href="attribute_generation.html" title="Attribute Generation">Attribute
Generation</a> section.
</p></td></tr>
</table></div>
<p>
If I run it in a shell, this is the result:
</p>
<pre class="programlisting">$ example/trivial
Enter a list of doubles, separated by commas. No pressure. 5.6,8.9
Great! It looks like you entered:
5.6
8.9
$ example/trivial
Enter a list of doubles, separated by commas. No pressure. 5.6, 8.9
Good job! Please proceed to the recovery annex for cake.
</pre>
<p>
It does not recognize <code class="computeroutput"><span class="string">"5.6, 8.9"</span></code>.
This is because it expects a comma followed <span class="emphasis"><em>immediately</em></span>
by a <code class="computeroutput"><span class="keyword">double</span></code>, but I inserted
a space after the comma. The same failure to parse would occur if I put a
space before the comma, or before or after the list of <code class="computeroutput"><span class="keyword">double</span></code>s.
</p>
<p>
One more thing: there is a much better way to write the parser above. Instead
of repeating the <code class="computeroutput"><span class="identifier">double_</span></code>
subparser, we could have written this:
</p>
<pre class="programlisting"><span class="identifier">bp</span><span class="special">::</span><span class="identifier">double_</span> <span class="special">%</span> <span class="char">','</span>
</pre>
<p>
That's semantically identical to <code class="computeroutput"><span class="identifier">bp</span><span class="special">::</span><span class="identifier">double_</span> <span class="special">&gt;&gt;</span> <span class="special">*(</span><span class="char">','</span> <span class="special">&gt;&gt;</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">double_</span><span class="special">)</span></code>. This pattern — some bit of input
repeated one or more times, with a separator between each instance —
comes up so often that there's an operator specifically for that, <code class="computeroutput"><span class="keyword">operator</span><span class="special">%</span></code>.
We'll be using that operator from now on.
</p>
</div>
<div class="copyright-footer">Copyright © 2020 T. Zachary Laine<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="hello__whomever.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="a_trivial_example_that_gracefully_handles_whitespace.html"><img src="../../images/next.png" alt="Next"></a>
</div>
</body>
</html>