mirror of
https://github.com/boostorg/parser.git
synced 2026-01-21 17:12:16 +00:00
1695 lines
132 KiB
HTML
1695 lines
132 KiB
HTML
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<title>Attribute Generation</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="combining_operations.html" title="Combining Operations">
|
||
<link rel="next" href="the__parse____api.html" title="The parse() API">
|
||
<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="combining_operations.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="the__parse____api.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.attribute_generation"></a><a class="link" href="attribute_generation.html" title="Attribute Generation">Attribute
|
||
Generation</a>
|
||
</h3></div></div></div>
|
||
<p>
|
||
So far, we've seen several different types of attributes that come from different
|
||
parsers, <code class="computeroutput"><span class="keyword">int</span></code> for <code class="computeroutput"><a class="link" href="../../boost/parser/int_.html" title="Global int_">int_</a></code>,
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="keyword">char</span><span class="special">,</span>
|
||
<span class="keyword">int</span><span class="special">></span></code>
|
||
for <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">char_</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="identifier">int_</span></code>, etc. Let's get into how this works
|
||
with more rigor.
|
||
</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>
|
||
Some parsers have no attribute at all. In the tables below, the type of
|
||
the attribute is listed as "None." There is a non-<code class="computeroutput"><span class="keyword">void</span></code> type that is returned from each parser
|
||
that lacks an attribute. This keeps the logic simple; having to handle
|
||
the two cases — <code class="computeroutput"><span class="keyword">void</span></code>
|
||
or non-<code class="computeroutput"><span class="keyword">void</span></code> — would
|
||
make the library significantly more complicated. The type of this non-<code class="computeroutput"><span class="keyword">void</span></code> attribute associated with these parsers
|
||
is an implementation detail. The type comes from the <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">detail</span></code>
|
||
namespace and is pretty useless. You should never see this type in practice.
|
||
Within semantic actions, asking for the attribute of a non-attribute-producing
|
||
parser (using <code class="computeroutput"><span class="identifier">_attr</span><span class="special">(</span><span class="identifier">ctx</span><span class="special">)</span></code>)
|
||
will yield a value of the special type <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">none</span></code>.
|
||
When calling <code class="computeroutput"><a class="link" href="../../boost/parser/parse_id2.html" title="Function template parse">parse()</a></code> in a form that returns
|
||
the attribute parsed, when there is no attribute, simply returns <code class="computeroutput"><span class="keyword">bool</span></code>; this indicates the success of failure
|
||
of the parse.
|
||
</p></td></tr>
|
||
</table></div>
|
||
<div class="warning"><table border="0" summary="Warning">
|
||
<tr>
|
||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../images/warning.png"></td>
|
||
<th align="left">Warning</th>
|
||
</tr>
|
||
<tr><td align="left" valign="top"><p>
|
||
Boost.Parser assumes that all attributes are semi-regular (see <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">semiregular</span></code>). Within the Boost.Parser
|
||
code, attributes are assigned, moved, copy, and default constructed. There
|
||
is no support for move-only or non-default-constructible types.
|
||
</p></td></tr>
|
||
</table></div>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h0"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation.the_attribute_type_trait___classname_alt__boost__parser__attribute___code__phrase_role__identifier__attribute__phrase___code___classname_"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation.the_attribute_type_trait___classname_alt__boost__parser__attribute___code__phrase_role__identifier__attribute__phrase___code___classname_">The
|
||
attribute type trait, attribute</a>
|
||
</h5>
|
||
<p>
|
||
You can use <code class="computeroutput"><a class="link" href="../../boost/parser/attribute.html" title="Struct template attribute">attribute</a></code>
|
||
(and the associated alias, <code class="computeroutput"><a class="link" href="../../boost/parser/attribute_t.html" title="Type definition attribute_t">attribute_t</a></code>) to determine the
|
||
attribute a parser would have if it were passed to <code class="computeroutput"><a class="link" href="../../boost/parser/parse_id2.html" title="Function template parse">parse()</a></code>.
|
||
Since at least one parser (<code class="computeroutput"><a class="link" href="../../boost/parser/char_.html" title="Global char_">char_</a></code>) has a polymorphic attribute
|
||
type, <code class="computeroutput"><a class="link" href="../../boost/parser/attribute.html" title="Struct template attribute">attribute</a></code>
|
||
also takes the type of the range being parsed. If a parser produces no attribute,
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/attribute.html" title="Struct template attribute">attribute</a></code>
|
||
will produce <code class="computeroutput"><a class="link" href="../../boost/parser/none.html" title="Struct none">none</a></code>,
|
||
not <code class="computeroutput"><span class="keyword">void</span></code>.
|
||
</p>
|
||
<p>
|
||
If you want to feed an iterator/sentinel pair to <code class="computeroutput"><a class="link" href="../../boost/parser/attribute.html" title="Struct template attribute">attribute</a></code>, create a range from
|
||
it like so:
|
||
</p>
|
||
<pre class="programlisting"><span class="keyword">constexpr</span> <span class="keyword">auto</span> <span class="identifier">parser</span> <span class="special">=</span> <span class="comment">/* ... */</span><span class="special">;</span>
|
||
<span class="keyword">auto</span> <span class="identifier">first</span> <span class="special">=</span> <span class="comment">/* ... */</span><span class="special">;</span>
|
||
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">last</span> <span class="special">=</span> <span class="comment">/* ... */</span><span class="special">;</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="comment">// You can of course use std::ranges::subrange directly in C++20 and later.</span>
|
||
<span class="keyword">using</span> <span class="identifier">attr_type</span> <span class="special">=</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">attribute_t</span><span class="special"><</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">BOOST_PARSER_SUBRANGE</span><span class="special">(</span><span class="identifier">first</span><span class="special">,</span> <span class="identifier">last</span><span class="special">)),</span> <span class="keyword">decltype</span><span class="special">(</span><span class="identifier">parser</span><span class="special">)>;</span>
|
||
</pre>
|
||
<p>
|
||
There is no single attribute type for any parser, since a parser can be placed
|
||
within <code class="computeroutput"><a class="link" href="../../boost/parser/omit.html" title="Global omit">omit[]</a></code>, which makes its attribute
|
||
type <code class="computeroutput"><a class="link" href="../../boost/parser/none.html" title="Struct none">none</a></code>.
|
||
Therefore, <code class="computeroutput"><a class="link" href="../../boost/parser/attribute.html" title="Struct template attribute">attribute</a></code>
|
||
cannot tell you what attribute your parser will produce under all circumstances;
|
||
it only tells you what it would produce if it were passed to <code class="computeroutput"><a class="link" href="../../boost/parser/parse_id2.html" title="Function template parse">parse()</a></code>.
|
||
</p>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h1"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation.parser_attributes"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation.parser_attributes">Parser
|
||
attributes</a>
|
||
</h5>
|
||
<p>
|
||
This table summarizes the attributes generated for all Boost.Parser parsers.
|
||
In the table below:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<span class="emphasis"><em><code class="literal">RESOLVE</code></em></span><code class="computeroutput"><span class="special">()</span></code>
|
||
is a notional macro that expands to the resolution of parse argument
|
||
or evaluation of a parse predicate (see <a class="link" href="the_parsers_and_their_uses.html" title="The Parsers And Their Uses">The
|
||
Parsers And Their Uses</a>); and
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">x</span></code> and <code class="computeroutput"><span class="identifier">y</span></code>
|
||
represent arbitrary objects.
|
||
</li>
|
||
</ul></div>
|
||
<div class="table">
|
||
<a name="boost_parser.tutorial.attribute_generation.t0"></a><p class="title"><b>Table 1.8. Parsers and Their Attributes</b></p>
|
||
<div class="table-contents"><table class="table" summary="Parsers and Their Attributes">
|
||
<colgroup>
|
||
<col>
|
||
<col>
|
||
<col>
|
||
</colgroup>
|
||
<thead><tr>
|
||
<th>
|
||
<p>
|
||
Parser
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Attribute Type
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Notes
|
||
</p>
|
||
</th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/eps.html" title="Global eps">eps</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
None.
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/eol.html" title="Global eol">eol</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
None.
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/eoi.html" title="Global eoi">eoi</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
None.
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/attr.html" title="Function template attr">attr</a><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">decltype</span><span class="special">(</span><span class="emphasis"><em><code class="literal">RESOLVE</code></em></span><span class="special">(</span><span class="identifier">x</span><span class="special">))</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/char_.html" title="Global char_">char_</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
The code point type in Unicode parsing, or <code class="computeroutput"><span class="keyword">char</span></code>
|
||
in non-Unicode parsing; see below.
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
Includes all the <code class="computeroutput"><span class="identifier">_p</span></code>
|
||
<a href="https://en.cppreference.com/w/cpp/language/user_literal" target="_top">UDLs</a>
|
||
that take a single character, and all character class parsers like
|
||
<code class="computeroutput"><span class="identifier">control</span></code> and <code class="computeroutput"><span class="identifier">lower</span></code>.
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/cp.html" title="Global cp">cp</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">char32_t</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/cu.html" title="Global cu">cu</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">char</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/lit_id9.html" title="Function lit">lit</a><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
None.
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
Includes all the <code class="computeroutput"><span class="identifier">_l</span></code>
|
||
<a href="https://en.cppreference.com/w/cpp/language/user_literal" target="_top">UDLs</a>.
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/string.html" title="Function template string">string</a><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
Includes all the <code class="computeroutput"><span class="identifier">_p</span></code>
|
||
<a href="https://en.cppreference.com/w/cpp/language/user_literal" target="_top">UDLs</a>
|
||
that take a string.
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/bool_.html" title="Global bool_">bool_</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">bool</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/bin.html" title="Global bin">bin</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">unsigned</span> <span class="keyword">int</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/oct.html" title="Global oct">oct</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">unsigned</span> <span class="keyword">int</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/hex.html" title="Global hex">hex</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">unsigned</span> <span class="keyword">int</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/ushort_.html" title="Global ushort_">ushort_</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">unsigned</span> <span class="keyword">short</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/uint_.html" title="Global uint_">uint_</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">unsigned</span> <span class="keyword">int</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/ulong_.html" title="Global ulong_">ulong_</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">unsigned</span> <span class="keyword">long</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/ulong_long.html" title="Global ulong_long">ulong_long</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">unsigned</span> <span class="keyword">long</span>
|
||
<span class="keyword">long</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/short_.html" title="Global short_">short_</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">short</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/int_.html" title="Global int_">int_</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">int</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/long_.html" title="Global long_">long_</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">long</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/long_long.html" title="Global long_long">long_long</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">long</span> <span class="keyword">long</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/float_.html" title="Global float_">float_</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">float</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/double_.html" title="Global double_">double_</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="keyword">double</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/symbols.html" title="Struct template symbols">symbols<T></a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">T</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table></div>
|
||
</div>
|
||
<br class="table-break"><p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/char_.html" title="Global char_">char_</a></code>
|
||
is a bit odd, since its attribute type is polymorphic. When you use <code class="computeroutput"><a class="link" href="../../boost/parser/char_.html" title="Global char_">char_</a></code>
|
||
to parse text in the non-Unicode code path (i.e. a string of <code class="computeroutput"><span class="keyword">char</span></code>), the attribute is <code class="computeroutput"><span class="keyword">char</span></code>.
|
||
When you use the exact same <code class="computeroutput"><a class="link" href="../../boost/parser/char_.html" title="Global char_">char_</a></code> to parse in the Unicode-aware
|
||
code path, all matching is code point based, and so the attribute type is
|
||
the type used to represent code points, <code class="computeroutput"><span class="keyword">char32_t</span></code>.
|
||
All parsing of UTF-8 falls under this case.
|
||
</p>
|
||
<p>
|
||
Here, we're parsing plain <code class="computeroutput"><span class="keyword">char</span></code>s,
|
||
meaning that the parsing is in the non-Unicode code path, the attribute of
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/char_.html" title="Global char_">char_</a></code>
|
||
is <code class="computeroutput"><span class="keyword">char</span></code>:
|
||
</p>
|
||
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">parse</span><span class="special">(</span><span class="string">"some text"</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="identifier">char_</span><span class="special">);</span>
|
||
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same_v</span><span class="special"><</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">result</span><span class="special">),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="keyword">char</span><span class="special">>>));</span>
|
||
</pre>
|
||
<p>
|
||
When you parse UTF-8, the matching is done on a code point basis, so the
|
||
attribute type is <code class="computeroutput"><span class="keyword">char32_t</span></code>:
|
||
</p>
|
||
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">parse</span><span class="special">(</span><span class="string">"some text"</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="identifier">as_utf8</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="identifier">char_</span><span class="special">);</span>
|
||
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same_v</span><span class="special"><</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">result</span><span class="special">),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="keyword">char32_t</span><span class="special">>>));</span>
|
||
</pre>
|
||
<p>
|
||
The good news is that usually you don't parse characters individually. When
|
||
you parse with <code class="computeroutput"><a class="link" href="../../boost/parser/char_.html" title="Global char_">char_</a></code>,
|
||
you usually parse repetition of then, which will produce a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
|
||
regardless of whether you're in Unicode parsing mode or not. If you do need
|
||
to parse individual characters, and want to lock down their attribute type,
|
||
you can use <code class="computeroutput"><a class="link" href="../../boost/parser/cp.html" title="Global cp">cp</a></code>
|
||
and/or <code class="computeroutput"><a class="link" href="../../boost/parser/cu.html" title="Global cu">cu</a></code>
|
||
to enforce a non-polymorphic attribute type.
|
||
</p>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h2"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation.combining_operation_attributes"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation.combining_operation_attributes">Combining
|
||
operation attributes</a>
|
||
</h5>
|
||
<p>
|
||
Combining operations of course affect the generation of attributes. In the
|
||
tables below:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">m</span></code> and <code class="computeroutput"><span class="identifier">n</span></code>
|
||
are parse arguments that resolve to integral values;
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">pred</span></code> is a parse predicate;
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">arg0</span></code>, <code class="computeroutput"><span class="identifier">arg1</span></code>,
|
||
<code class="computeroutput"><span class="identifier">arg2</span></code>, ... are parse arguments;
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">a</span></code> is a semantic action;
|
||
and
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">p</span></code>, <code class="computeroutput"><span class="identifier">p1</span></code>,
|
||
<code class="computeroutput"><span class="identifier">p2</span></code>, ... are parsers that
|
||
generate attributes.
|
||
</li>
|
||
</ul></div>
|
||
<div class="table">
|
||
<a name="boost_parser.tutorial.attribute_generation.t1"></a><p class="title"><b>Table 1.9. Combining Operations and Their Attributes</b></p>
|
||
<div class="table-contents"><table class="table" summary="Combining Operations and Their Attributes">
|
||
<colgroup>
|
||
<col>
|
||
<col>
|
||
</colgroup>
|
||
<thead><tr>
|
||
<th>
|
||
<p>
|
||
Parser
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Attribute Type
|
||
</p>
|
||
</th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">!</span><span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
None.
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">&</span><span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
None.
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">*</span><span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">+</span><span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">+*</span><span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">*+</span><span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">-</span><span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">>></span>
|
||
<span class="identifier">p2</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">></span>
|
||
<span class="identifier">p2</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">>></span>
|
||
<span class="identifier">p2</span> <span class="special">>></span>
|
||
<span class="identifier">p3</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p3</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">></span>
|
||
<span class="identifier">p2</span> <span class="special">>></span>
|
||
<span class="identifier">p3</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p3</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">>></span>
|
||
<span class="identifier">p2</span> <span class="special">></span>
|
||
<span class="identifier">p3</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p3</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">></span>
|
||
<span class="identifier">p2</span> <span class="special">></span>
|
||
<span class="identifier">p3</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p3</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">|</span>
|
||
<span class="identifier">p2</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">|</span>
|
||
<span class="identifier">p2</span> <span class="special">|</span>
|
||
<span class="identifier">p3</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p3</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">||</span>
|
||
<span class="identifier">p2</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">||</span>
|
||
<span class="identifier">p2</span> <span class="special">||</span>
|
||
<span class="identifier">p3</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p3</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">%</span>
|
||
<span class="identifier">p2</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p</span><span class="special">[</span><span class="identifier">a</span><span class="special">]</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
None.
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/repeat_id13.html" title="Function template repeat">repeat</a><span class="special">(</span><span class="identifier">arg0</span><span class="special">)[</span><span class="identifier">p</span><span class="special">]</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/repeat_id13.html" title="Function template repeat">repeat</a><span class="special">(</span><span class="identifier">arg0</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">)[</span><span class="identifier">p</span><span class="special">]</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/if_.html" title="Function template if_">if_</a><span class="special">(</span><span class="identifier">pred</span><span class="special">)[</span><span class="identifier">p</span><span class="special">]</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/switch_.html" title="Function template switch_">switch_</a><span class="special">(</span><span class="identifier">arg0</span><span class="special">)(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">p1</span><span class="special">)(</span><span class="identifier">arg2</span><span class="special">,</span> <span class="identifier">p2</span><span class="special">)...</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">),</span> <span class="special">...></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table></div>
|
||
</div>
|
||
<br class="table-break"><div class="important"><table border="0" summary="Important">
|
||
<tr>
|
||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../images/important.png"></td>
|
||
<th align="left">Important</th>
|
||
</tr>
|
||
<tr><td align="left" valign="top"><p>
|
||
All the character parsers, like <code class="computeroutput"><a class="link" href="../../boost/parser/char_.html" title="Global char_">char_</a></code>, <code class="computeroutput"><a class="link" href="../../boost/parser/cp.html" title="Global cp">cp</a></code> and <code class="computeroutput"><a class="link" href="../../boost/parser/cu.html" title="Global cu">cu</a></code> produce either <code class="computeroutput"><span class="keyword">char</span></code> or <code class="computeroutput"><span class="keyword">char32_t</span></code>
|
||
attributes. So when you see "<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||
if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is
|
||
<code class="computeroutput"><span class="keyword">char</span></code> or <code class="computeroutput"><span class="keyword">char32_t</span></code>,
|
||
otherwise <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>"
|
||
in the table above, that effectively means that every sequences of character
|
||
attributes get turned into a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
|
||
The only time this does not happen is when you introduce your own rules
|
||
with attributes using another character type (or use <code class="computeroutput"><a class="link" href="../../boost/parser/attribute.html" title="Struct template attribute">attribute</a></code> to do so).
|
||
</p></td></tr>
|
||
</table></div>
|
||
<div class="important"><table border="0" summary="Important">
|
||
<tr>
|
||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../images/important.png"></td>
|
||
<th align="left">Important</th>
|
||
</tr>
|
||
<tr><td align="left" valign="top"><p>
|
||
In case you did not notice it above, adding a semantic action to a parser
|
||
erases the parser's attribute. The attribute is still available inside
|
||
the semantic action as <code class="computeroutput"><span class="identifier">_attr</span><span class="special">(</span><span class="identifier">ctx</span><span class="special">)</span></code>.
|
||
</p></td></tr>
|
||
</table></div>
|
||
<p>
|
||
There are a relatively small number of rules that define how sequence parsers
|
||
and alternative parsers' attributes are generated. (Don't worry, there are
|
||
examples below.)
|
||
</p>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h3"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation.sequence_parser_attribute_rules"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation.sequence_parser_attribute_rules">Sequence
|
||
parser attribute rules</a>
|
||
</h5>
|
||
<p>
|
||
The attribute generation behavior of sequence parsers is conceptually pretty
|
||
simple:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
the attributes of subparsers form a tuple of values;
|
||
</li>
|
||
<li class="listitem">
|
||
subparsers that do not generate attributes do not contribute to the sequence's
|
||
attribute;
|
||
</li>
|
||
<li class="listitem">
|
||
subparsers that do generate attributes usually contribute an individual
|
||
element to the tuple result; except
|
||
</li>
|
||
<li class="listitem">
|
||
when containers of the same element type are next to each other, or individual
|
||
elements are next to containers of their type, the two adjacent attributes
|
||
collapse into one attribute; and
|
||
</li>
|
||
<li class="listitem">
|
||
if the result of all that is a degenerate tuple <code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||
(even if <code class="computeroutput"><span class="identifier">T</span></code> is a type
|
||
that means "no attribute"), the attribute becomes <code class="computeroutput"><span class="identifier">T</span></code>.
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
More formally, the attribute generation algorithm works like this. For a
|
||
sequence parser <code class="computeroutput"><span class="identifier">p</span></code>, let the
|
||
list of attribute types for the subparsers of <code class="computeroutput"><span class="identifier">p</span></code>
|
||
be <code class="computeroutput"><span class="identifier">a0</span><span class="special">,</span>
|
||
<span class="identifier">a1</span><span class="special">,</span> <span class="identifier">a2</span><span class="special">,</span> <span class="special">...,</span>
|
||
<span class="identifier">an</span></code>.
|
||
</p>
|
||
<p>
|
||
We get the attribute of <code class="computeroutput"><span class="identifier">p</span></code>
|
||
by evaluating a compile-time left fold operation, <code class="computeroutput"><span class="identifier">left</span><span class="special">-</span><span class="identifier">fold</span><span class="special">({</span><span class="identifier">a1</span><span class="special">,</span> <span class="identifier">a2</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">an</span><span class="special">},</span> <span class="identifier">tuple</span><span class="special"><</span><span class="identifier">a0</span><span class="special">>,</span> <span class="identifier">OP</span><span class="special">)</span></code>. <code class="computeroutput"><span class="identifier">OP</span></code>
|
||
is the combining operation that takes the current attribute type (initially
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="identifier">a0</span><span class="special">></span></code>) and the next attribute type, and returns
|
||
the new current attribute type. The current attribute type at the end of
|
||
the fold operation is the attribute type for <code class="computeroutput"><span class="identifier">p</span></code>.
|
||
</p>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">OP</span></code> attempts to apply a series
|
||
of rules, one at a time. The rules are noted as <code class="computeroutput"><span class="identifier">X</span>
|
||
<span class="special">>></span> <span class="identifier">Y</span>
|
||
<span class="special">-></span> <span class="identifier">Z</span></code>,
|
||
where <code class="computeroutput"><span class="identifier">X</span></code> is the type of the
|
||
current attribute, <code class="computeroutput"><span class="identifier">Y</span></code> is the
|
||
type of the next attribute, and <code class="computeroutput"><span class="identifier">Z</span></code>
|
||
is the new current attribute type. In these rules, <code class="computeroutput"><span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||
is a container of <code class="computeroutput"><span class="identifier">T</span></code>; <code class="computeroutput"><span class="identifier">none</span></code> is a special type that indicates that
|
||
there is no attribute; <code class="computeroutput"><span class="identifier">T</span></code>
|
||
is a type; <code class="computeroutput"><span class="identifier">CHAR</span></code> is a character
|
||
type, either <code class="computeroutput"><span class="keyword">char</span></code> or <code class="computeroutput"><span class="keyword">char32_t</span></code>; and <code class="computeroutput"><span class="identifier">Ts</span><span class="special">...</span></code> is a parameter pack of one or more types.
|
||
Note that <code class="computeroutput"><span class="identifier">T</span></code> may be the special
|
||
type <code class="computeroutput"><span class="identifier">none</span></code>. The current attribute
|
||
is always a tuple (call it <code class="computeroutput"><span class="identifier">Tup</span></code>),
|
||
so the "current attribute <code class="computeroutput"><span class="identifier">X</span></code>"
|
||
refers to the last element of <code class="computeroutput"><span class="identifier">Tup</span></code>,
|
||
not <code class="computeroutput"><span class="identifier">Tup</span></code> itself, except for
|
||
those rules that explicitly mention <code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><></span></code>
|
||
as part of <code class="computeroutput"><span class="identifier">X</span></code>'s type.
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">none</span> <span class="special">>></span>
|
||
<span class="identifier">T</span> <span class="special">-></span>
|
||
<span class="identifier">T</span></code>
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">CHAR</span></code> >> <code class="computeroutput"><span class="identifier">CHAR</span></code> -> <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">T</span> <span class="special">>></span>
|
||
<span class="identifier">none</span> <span class="special">-></span>
|
||
<span class="identifier">T</span></code>
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">>></span> <span class="identifier">T</span>
|
||
<span class="special">-></span> <span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">T</span> <span class="special">>></span>
|
||
<span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">-></span> <span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">>></span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">-></span> <span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">>></span> <span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">-></span> <span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="identifier">none</span><span class="special">></span> <span class="special">>></span>
|
||
<span class="identifier">T</span> <span class="special">-></span>
|
||
<a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="identifier">Ts</span><span class="special">...></span> <span class="special">>></span>
|
||
<span class="identifier">T</span> <span class="special">-></span>
|
||
<a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="identifier">Ts</span><span class="special">...,</span> <span class="identifier">T</span><span class="special">></span></code>
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
The rules that combine containers with (possibly optional) adjacent values
|
||
(e.g. <code class="computeroutput"><span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">>></span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span>
|
||
<span class="special">-></span> <span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>)
|
||
have a special case for strings. If <code class="computeroutput"><span class="identifier">C</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||
is exactly <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>, and <code class="computeroutput"><span class="identifier">T</span></code>
|
||
is either <code class="computeroutput"><span class="keyword">char</span></code> or <code class="computeroutput"><span class="keyword">char32_t</span></code>, the combination yields a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
|
||
</p>
|
||
<p>
|
||
Again, if the final result is that the attribute is <code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>,
|
||
the attribute becomes <code class="computeroutput"><span class="identifier">T</span></code>.
|
||
</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>
|
||
What constitutes a container in the rules above is determined by the <code class="computeroutput"><span class="identifier">container</span></code> concept:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||
<span class="identifier">concept</span> <span class="identifier">container</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ranges</span><span class="special">::</span><span class="identifier">common_range</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">&&</span> <span class="identifier">requires</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">t</span><span class="special">)</span> <span class="special">{</span>
|
||
<span class="special">{</span> <span class="identifier">t</span><span class="special">.</span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">t</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="special">*</span><span class="identifier">t</span><span class="special">.</span><span class="identifier">begin</span><span class="special">())</span> <span class="special">}</span>
|
||
<span class="special">-></span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">same_as</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ranges</span><span class="special">::</span><span class="identifier">iterator_t</span><span class="special"><</span><span class="identifier">T</span><span class="special">>>;</span>
|
||
<span class="special">};</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
</td></tr>
|
||
</table></div>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h4"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation.alternative_parser_attribute_rules"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation.alternative_parser_attribute_rules">Alternative
|
||
parser attribute rules</a>
|
||
</h5>
|
||
<p>
|
||
The rules for alternative parsers are much simpler. For an alternative parer
|
||
<code class="computeroutput"><span class="identifier">p</span></code>, let the list of attribute
|
||
types for the subparsers of <code class="computeroutput"><span class="identifier">p</span></code>
|
||
be <code class="computeroutput"><span class="identifier">a0</span><span class="special">,</span>
|
||
<span class="identifier">a1</span><span class="special">,</span> <span class="identifier">a2</span><span class="special">,</span> <span class="special">...,</span>
|
||
<span class="identifier">an</span></code>. The attribute of <code class="computeroutput"><span class="identifier">p</span></code> is <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="identifier">a0</span><span class="special">,</span> <span class="identifier">a1</span><span class="special">,</span>
|
||
<span class="identifier">a2</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">an</span><span class="special">></span></code>, with the following steps applied:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
all the <code class="computeroutput"><span class="identifier">none</span></code> attributes
|
||
are left out, and if any are, the attribute is wrapped in a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span></code>, like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"></*...*/>></span></code>;
|
||
</li>
|
||
<li class="listitem">
|
||
duplicates in the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span></code>
|
||
template parameters <code class="computeroutput"><span class="special"><</span><span class="identifier">T1</span><span class="special">,</span> <span class="identifier">T2</span><span class="special">,</span> <span class="special">...</span> <span class="identifier">Tn</span><span class="special">></span></code> are removed; every type that appears
|
||
does so exacly once;
|
||
</li>
|
||
<li class="listitem">
|
||
if the attribute is <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> or <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="identifier">T</span><span class="special">>></span></code>, the attribute becomes instead
|
||
<code class="computeroutput"><span class="identifier">T</span></code> or <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>, respectively; and
|
||
</li>
|
||
<li class="listitem">
|
||
if the attribute is <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><></span></code> or <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><>></span></code>, the result becomes <code class="computeroutput"><span class="identifier">none</span></code> instead.
|
||
</li>
|
||
</ul></div>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h5"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation.formation_of_containers_in_attributes"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation.formation_of_containers_in_attributes">Formation
|
||
of containers in attributes</a>
|
||
</h5>
|
||
<p>
|
||
The rule for forming containers from non-containers is simple. You get a
|
||
vector from any of the repeating parsers, like <code class="computeroutput"><span class="special">+</span><span class="identifier">p</span></code>, <code class="computeroutput"><span class="special">*</span><span class="identifier">p</span></code>, <code class="computeroutput"><span class="identifier">repeat</span><span class="special">(</span><span class="number">3</span><span class="special">)[</span><span class="identifier">p</span><span class="special">]</span></code>, etc.
|
||
The value type of the vector is <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code>.
|
||
</p>
|
||
<p>
|
||
Another rule for sequence containers is that a value <code class="computeroutput"><span class="identifier">x</span></code>
|
||
and a container <code class="computeroutput"><span class="identifier">c</span></code> containing
|
||
elements of <code class="computeroutput"><span class="identifier">x</span></code>'s type will
|
||
form a single container. However, <code class="computeroutput"><span class="identifier">x</span></code>'s
|
||
type must be exactly the same as the elements in <code class="computeroutput"><span class="identifier">c</span></code>.
|
||
There is an exception to this in the special case for strings and characters
|
||
noted above. For instance, consider the attribute of <code class="computeroutput"><span class="identifier">char_</span>
|
||
<span class="special">>></span> <span class="identifier">string</span><span class="special">(</span><span class="string">"str"</span><span class="special">)</span></code>. In the non-Unicode code path, <code class="computeroutput"><span class="identifier">char_</span></code>'s attribute type is guaranteed to
|
||
be <code class="computeroutput"><span class="keyword">char</span></code>, so <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">char_</span> <span class="special">>></span> <span class="identifier">string</span><span class="special">(</span><span class="string">"str"</span><span class="special">))</span></code> is <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
|
||
If you are parsing UTF-8 in the Unicode code path, <code class="computeroutput"><span class="identifier">char_</span></code>'s
|
||
attribute type is <code class="computeroutput"><span class="keyword">char32_t</span></code>,
|
||
and the special rule makes it also produce a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
|
||
Otherwise, the attribute for <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">char_</span> <span class="special">>></span> <span class="identifier">string</span><span class="special">(</span><span class="string">"str"</span><span class="special">))</span></code> would be <code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="keyword">char32_t</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">></span></code>.
|
||
</p>
|
||
<p>
|
||
Again, there are no special rules for combining values and containers. Every
|
||
combination results from an exact match, or fall into the string+character
|
||
special case.
|
||
</p>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h6"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation.another_special_case___code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__string__phrase___code__assignment"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation.another_special_case___code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__string__phrase___code__assignment">Another
|
||
special case: <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> assignment</a>
|
||
</h5>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> can be assigned from a <code class="computeroutput"><span class="keyword">char</span></code>. This is dumb. But, we're stuck with
|
||
it. When you write a parser with a <code class="computeroutput"><span class="keyword">char</span></code>
|
||
attribute, and you try to parse it into a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
|
||
you've almost certainly made a mistake. More importantly, if you write this:
|
||
</p>
|
||
<pre class="programlisting"><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="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">result</span><span class="special">;</span>
|
||
<span class="keyword">auto</span> <span class="identifier">b</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="string">"3"</span><span class="special">,</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">int_</span><span class="special">,</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">ws</span><span class="special">,</span> <span class="identifier">result</span><span class="special">);</span>
|
||
</pre>
|
||
<p>
|
||
... you are even more likely to have made a mistake. Though this should work,
|
||
because the assignment in <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">s</span><span class="special">;</span> <span class="identifier">s</span>
|
||
<span class="special">=</span> <span class="number">3</span><span class="special">;</span></code> is well-formed, Boost.Parser forbids it.
|
||
If you write parsing code like the snippet above, you will get a static assertion.
|
||
If you really do want to assign a <code class="computeroutput"><span class="keyword">float</span></code>
|
||
or whatever to a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>, do it in a semantic action.
|
||
</p>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h7"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation.examples_of_attributes_generated_by_sequence_and_alternative_parsers"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation.examples_of_attributes_generated_by_sequence_and_alternative_parsers">Examples
|
||
of attributes generated by sequence and alternative parsers</a>
|
||
</h5>
|
||
<p>
|
||
In the table: <code class="computeroutput"><span class="identifier">a</span></code> is a semantic
|
||
action; and <code class="computeroutput"><span class="identifier">p</span></code>, <code class="computeroutput"><span class="identifier">p1</span></code>, <code class="computeroutput"><span class="identifier">p2</span></code>,
|
||
... are parsers that generate attributes. Note that only <code class="computeroutput"><span class="special">>></span></code>
|
||
is used here; <code class="computeroutput"><span class="special">></span></code> has the exact
|
||
same attribute generation rules.
|
||
</p>
|
||
<div class="table">
|
||
<a name="boost_parser.tutorial.attribute_generation.t2"></a><p class="title"><b>Table 1.10. Sequence and Alternative Combining Operations and Their Attributes</b></p>
|
||
<div class="table-contents"><table class="table" summary="Sequence and Alternative Combining Operations and Their Attributes">
|
||
<colgroup>
|
||
<col>
|
||
<col>
|
||
</colgroup>
|
||
<thead><tr>
|
||
<th>
|
||
<p>
|
||
Expression
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Attribute Type
|
||
</p>
|
||
</th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/eps.html" title="Global eps">eps</a>
|
||
<span class="special">>></span> <a class="link" href="../../boost/parser/eps.html" title="Global eps">eps</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
None.
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p</span> <span class="special">>></span>
|
||
<a class="link" href="../../boost/parser/eps.html" title="Global eps">eps</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/eps.html" title="Global eps">eps</a>
|
||
<span class="special">>></span> <span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/cu.html" title="Global cu">cu</a>
|
||
<span class="special">>></span> <a class="link" href="../../boost/parser/string.html" title="Function template string">string</a><span class="special">(</span><span class="string">"str"</span><span class="special">)</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/string.html" title="Function template string">string</a><span class="special">(</span><span class="string">"str"</span><span class="special">)</span> <span class="special">>></span>
|
||
<a class="link" href="../../boost/parser/cu.html" title="Global cu">cu</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">*</span><a class="link" href="../../boost/parser/cu.html" title="Global cu">cu</a> <span class="special">>></span>
|
||
<a class="link" href="../../boost/parser/string.html" title="Function template string">string</a><span class="special">(</span><span class="string">"str"</span><span class="special">)</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/string.html" title="Function template string">string</a><span class="special">(</span><span class="string">"str"</span><span class="special">)</span> <span class="special">>></span>
|
||
<span class="special">*</span><a class="link" href="../../boost/parser/cu.html" title="Global cu">cu</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p</span> <span class="special">>></span>
|
||
<span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">*</span><span class="identifier">p</span>
|
||
<span class="special">>></span> <span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p</span> <span class="special">>></span>
|
||
<span class="special">*</span><span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">*</span><span class="identifier">p</span>
|
||
<span class="special">>></span> <span class="special">-</span><span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">-</span><span class="identifier">p</span>
|
||
<span class="special">>></span> <span class="special">*</span><span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> if <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> is <code class="computeroutput"><span class="keyword">char</span></code>
|
||
or <code class="computeroutput"><span class="keyword">char32_t</span></code>, otherwise
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/string.html" title="Function template string">string</a><span class="special">(</span><span class="string">"str"</span><span class="special">)</span> <span class="special">>></span>
|
||
<span class="special">-</span><a class="link" href="../../boost/parser/cu.html" title="Global cu">cu</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">-</span><a class="link" href="../../boost/parser/cu.html" title="Global cu">cu</a> <span class="special">>></span>
|
||
<a class="link" href="../../boost/parser/string.html" title="Function template string">string</a><span class="special">(</span><span class="string">"str"</span><span class="special">)</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="special">!</span><span class="identifier">p1</span>
|
||
<span class="special">|</span> <span class="identifier">p2</span><span class="special">[</span><span class="identifier">a</span><span class="special">]</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
None.
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p</span> <span class="special">|</span>
|
||
<span class="identifier">p</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">|</span>
|
||
<span class="identifier">p2</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p</span> <span class="special">|</span>
|
||
</code><code class="computeroutput"><a class="link" href="../../boost/parser/eps.html" title="Global eps">eps</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">|</span>
|
||
<span class="identifier">p2</span> <span class="special">|</span>
|
||
<a class="link" href="../../boost/parser/eps.html" title="Global eps">eps</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p2</span><span class="special">)>></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">p1</span> <span class="special">|</span>
|
||
<span class="identifier">p2</span><span class="special">[</span><span class="identifier">a</span><span class="special">]</span>
|
||
<span class="special">|</span> <span class="identifier">p3</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p1</span><span class="special">),</span> <span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p3</span><span class="special">)>></span></code>
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table></div>
|
||
</div>
|
||
<br class="table-break"><h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h8"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation.controlling_attribute_generation_with__globalname_alt__boost__parser__merge___code__phrase_role__identifier__merge__phrase__phrase_role__special______phrase___code___globalname__and__globalname_alt__boost__parser__separate___code__phrase_role__identifier__separate__phrase__phrase_role__special______phrase___code___globalname_"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation.controlling_attribute_generation_with__globalname_alt__boost__parser__merge___code__phrase_role__identifier__merge__phrase__phrase_role__special______phrase___code___globalname__and__globalname_alt__boost__parser__separate___code__phrase_role__identifier__separate__phrase__phrase_role__special______phrase___code___globalname_">Controlling
|
||
attribute generation with merge[]
|
||
and separate[]</a>
|
||
</h5>
|
||
<p>
|
||
As we saw in the previous <a class="link" href="parsing_into__struct_s_and__class_es.html" title="Parsing into structs and classes">Parsing
|
||
into <code class="computeroutput"><span class="keyword">struct</span></code>s and <code class="computeroutput"><span class="keyword">class</span></code>es</a> section, if you parse two strings
|
||
in a row, you get two separate strings in the resulting attribute. The parser
|
||
from that example was this:
|
||
</p>
|
||
<pre class="programlisting"><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">auto</span> <span class="identifier">employee_parser</span> <span class="special">=</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">lit</span><span class="special">(</span><span class="string">"employee"</span><span class="special">)</span>
|
||
<span class="special">>></span> <span class="char">'{'</span>
|
||
<span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">int_</span> <span class="special">>></span> <span class="char">','</span>
|
||
<span class="special">>></span> <span class="identifier">quoted_string</span> <span class="special">>></span> <span class="char">','</span>
|
||
<span class="special">>></span> <span class="identifier">quoted_string</span> <span class="special">>></span> <span class="char">','</span>
|
||
<span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">double_</span>
|
||
<span class="special">>></span> <span class="char">'}'</span><span class="special">;</span>
|
||
</pre>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">employee_parser</span></code>'s attribute
|
||
is <code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="keyword">int</span><span class="special">,</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">></span></code>.
|
||
The two <code class="computeroutput"><span class="identifier">quoted_string</span></code> parsers
|
||
produce <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> attributes, and those attributes
|
||
are not combined. That is the default behavior, and it is just what we want
|
||
for this case; we don't want the first and last name fields to be jammed
|
||
together such that we can't tell where one name ends and the other begins.
|
||
What if we were parsing some string that consisted of a prefix and a suffix,
|
||
and the prefix and suffix were defined separately for reuse elsewhere?
|
||
</p>
|
||
<pre class="programlisting"><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">auto</span> <span class="identifier">prefix</span> <span class="special">=</span> <span class="comment">/* ... */</span><span class="special">;</span>
|
||
<span class="keyword">auto</span> <span class="identifier">suffix</span> <span class="special">=</span> <span class="comment">/* ... */</span><span class="special">;</span>
|
||
<span class="keyword">auto</span> <span class="identifier">special_string</span> <span class="special">=</span> <span class="identifier">prefix</span> <span class="special">>></span> <span class="identifier">suffix</span><span class="special">;</span>
|
||
<span class="comment">// Continue to use prefix and suffix to make other parsers....</span>
|
||
</pre>
|
||
<p>
|
||
In this case, we might want to use these separate parsers, but want <code class="computeroutput"><span class="identifier">special_string</span></code> to produce a single <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||
for its attribute. <code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code> exists for this purpose.
|
||
</p>
|
||
<pre class="programlisting"><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">auto</span> <span class="identifier">prefix</span> <span class="special">=</span> <span class="comment">/* ... */</span><span class="special">;</span>
|
||
<span class="keyword">auto</span> <span class="identifier">suffix</span> <span class="special">=</span> <span class="comment">/* ... */</span><span class="special">;</span>
|
||
<span class="keyword">auto</span> <span class="identifier">special_string</span> <span class="special">=</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">merge</span><span class="special">[</span><span class="identifier">prefix</span> <span class="special">>></span> <span class="identifier">suffix</span><span class="special">];</span>
|
||
</pre>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code> only applies to sequence parsers
|
||
(like <code class="computeroutput"><span class="identifier">p1</span> <span class="special">>></span>
|
||
<span class="identifier">p2</span></code>), and forces all subparsers
|
||
in the sequence parser to use the same variable for their attribute.
|
||
</p>
|
||
<p>
|
||
Another directive, <code class="computeroutput"><a class="link" href="../../boost/parser/separate.html" title="Global separate">separate[]</a></code>,
|
||
also applies only to sequence parsers, but does the opposite of <code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code>. If forces all the attributes
|
||
produced by the subparsers of the sequence parser to stay separate, even
|
||
if they would have combined. For instance, consider this parser.
|
||
</p>
|
||
<pre class="programlisting"><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">auto</span> <span class="identifier">string_and_char</span> <span class="special">=</span> <span class="special">+</span><span class="identifier">bp</span><span class="special">::</span><span class="identifier">char_</span><span class="special">(</span><span class="char">'a'</span><span class="special">)</span> <span class="special">>></span> <span class="char">' '</span> <span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">cp</span><span class="special">;</span>
|
||
</pre>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">string_and_char</span></code> matches one
|
||
or more <code class="computeroutput"><span class="char">'a'</span></code>s, followed by some
|
||
other character. As written above, <code class="computeroutput"><span class="identifier">string_and_char</span></code>
|
||
produces a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>, and the final character is appended
|
||
to the string, after all the <code class="computeroutput"><span class="char">'a'</span></code>s.
|
||
However, if you wanted to store the final character as a separate value,
|
||
you would use <code class="computeroutput"><a class="link" href="../../boost/parser/separate.html" title="Global separate">separate[]</a></code>.
|
||
</p>
|
||
<pre class="programlisting"><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">auto</span> <span class="identifier">string_and_char</span> <span class="special">=</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">separate</span><span class="special">[+</span><span class="identifier">bp</span><span class="special">::</span><span class="identifier">char_</span><span class="special">(</span><span class="char">'a'</span><span class="special">)</span> <span class="special">>></span> <span class="char">' '</span> <span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">cp</span><span class="special">];</span>
|
||
</pre>
|
||
<p>
|
||
With this change, <code class="computeroutput"><span class="identifier">string_and_char</span></code>
|
||
produces the attribute <code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">char32_t</span><span class="special">></span></code>.
|
||
</p>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h9"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation._globalname_alt__boost__parser__merge___code__phrase_role__identifier__merge__phrase__phrase_role__special______phrase___code___globalname__and__globalname_alt__boost__parser__separate___code__phrase_role__identifier__separate__phrase__phrase_role__special______phrase___code___globalname__in_more_detail"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation._globalname_alt__boost__parser__merge___code__phrase_role__identifier__merge__phrase__phrase_role__special______phrase___code___globalname__and__globalname_alt__boost__parser__separate___code__phrase_role__identifier__separate__phrase__phrase_role__special______phrase___code___globalname__in_more_detail">merge[] and separate[]
|
||
in more detail</a>
|
||
</h5>
|
||
<p>
|
||
As mentioned previously, <code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code>
|
||
applies only to sequence parsers. All subparsers must have the same attribute,
|
||
or produce no attribute at all. At least one subparser must produce an attribute.
|
||
When you use <code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code>, you create a <span class="emphasis"><em>combining
|
||
group</em></span>. Every parser in a combining group uses the same variable
|
||
for its attribute. No parser in a combining group interacts with the attributes
|
||
of any parsers outside of its combining group. Combining groups are disjoint;
|
||
<code class="computeroutput"><span class="identifier">merge</span><span class="special">[/*...*/]</span>
|
||
<span class="special">>></span> <span class="identifier">merge</span><span class="special">[/*...*/]</span></code> will produce a tuple of two attributes,
|
||
not one.
|
||
</p>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/separate.html" title="Global separate">separate[]</a></code> also applies only to sequence
|
||
parsers. When you use <code class="computeroutput"><a class="link" href="../../boost/parser/separate.html" title="Global separate">separate[]</a></code>,
|
||
you disable interaction of all the subparsers' attributes with adjacent attributes,
|
||
whether they are inside or outside the <code class="computeroutput"><a class="link" href="../../boost/parser/separate.html" title="Global separate">separate[]</a></code>
|
||
directive; you force each subparser to have a separate attribute.
|
||
</p>
|
||
<p>
|
||
The rules for <code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code> and <code class="computeroutput"><a class="link" href="../../boost/parser/separate.html" title="Global separate">separate[]</a></code>
|
||
overrule the steps of the algorithm described above for combining the attributes
|
||
of a sequence parser. Consider an example.
|
||
</p>
|
||
<pre class="programlisting"><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">constexpr</span> <span class="keyword">auto</span> <span class="identifier">parser</span> <span class="special">=</span>
|
||
<span class="identifier">bp</span><span class="special">::</span><span class="identifier">char_</span> <span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">merge</span><span class="special">[(</span><span class="identifier">bp</span><span class="special">::</span><span class="identifier">string</span><span class="special">(</span><span class="string">"abc"</span><span class="special">)</span> <span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">char_</span> <span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">char_</span><span class="special">)</span> <span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">string</span><span class="special">(</span><span class="string">"ghi"</span><span class="special">)];</span>
|
||
</pre>
|
||
<p>
|
||
You might think that <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">parser</span><span class="special">)</span></code> would be <code class="computeroutput"><span class="identifier">bp</span><span class="special">::</span><span class="identifier">tuple</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">></span></code>.
|
||
It is not. The parser above does not even compile. Since we created a merge
|
||
group above, we disabled the default behavior in which the <code class="computeroutput"><span class="identifier">char_</span></code> parsers would have collapsed into
|
||
the <code class="computeroutput"><span class="identifier">string</span></code> parser that preceded
|
||
them. Since they are all treated as separate entities, and since they have
|
||
different attribute types, the use of <code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code>
|
||
is an error.
|
||
</p>
|
||
<p>
|
||
Many directives create a new parser out of the parser they are given. <code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code> and <code class="computeroutput"><a class="link" href="../../boost/parser/separate.html" title="Global separate">separate[]</a></code>
|
||
do not. Since they operate only on sequence parsers, all they do is create
|
||
a copy of the sequence parser they are given. The <code class="computeroutput"><a class="link" href="../../boost/parser/seq_parser.html" title="Struct template seq_parser">seq_parser</a></code> template has a template
|
||
parameter <code class="computeroutput"><span class="identifier">CombiningGroups</span></code>,
|
||
and all <code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code> and <code class="computeroutput"><a class="link" href="../../boost/parser/separate.html" title="Global separate">separate[]</a></code>
|
||
do is take a given <code class="computeroutput"><a class="link" href="../../boost/parser/seq_parser.html" title="Struct template seq_parser">seq_parser</a></code> and create a copy
|
||
of it with a different <code class="computeroutput"><span class="identifier">CombiningGroups</span></code>
|
||
template parameter. This means that <code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code>
|
||
and <code class="computeroutput"><a class="link" href="../../boost/parser/separate.html" title="Global separate">separate[]</a></code> are can be ignored in <code class="computeroutput"><span class="keyword">operator</span><span class="special">>></span></code>
|
||
expressions much like parentheses are. Consider an example.
|
||
</p>
|
||
<pre class="programlisting"><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">constexpr</span> <span class="keyword">auto</span> <span class="identifier">parser1</span> <span class="special">=</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">separate</span><span class="special">[</span><span class="identifier">bp</span><span class="special">::</span><span class="identifier">int_</span> <span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">int_</span><span class="special">]</span> <span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">int_</span><span class="special">;</span>
|
||
<span class="keyword">constexpr</span> <span class="keyword">auto</span> <span class="identifier">parser2</span> <span class="special">=</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">lexeme</span><span class="special">[</span><span class="identifier">bp</span><span class="special">::</span><span class="identifier">int_</span> <span class="special">>></span> <span class="char">' '</span> <span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">int_</span><span class="special">]</span> <span class="special">>></span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">int_</span><span class="special">;</span>
|
||
</pre>
|
||
<p>
|
||
Note that <code class="computeroutput"><a class="link" href="../../boost/parser/separate.html" title="Global separate">separate[]</a></code> is a no-op here; it's only
|
||
being used this way for this example. These parsers have different attribute
|
||
types. <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">parser1</span><span class="special">)</span></code>
|
||
is <code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special">(</span><span class="keyword">int</span><span class="special">,</span>
|
||
<span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span></code>. <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">parser2</span><span class="special">)</span></code> is <code class="computeroutput"><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special">(</span><a class="link" href="../../boost/parser/tuple.html" title="Type definition tuple">boost::parser::tuple</a><span class="special">(</span><span class="keyword">int</span><span class="special">,</span>
|
||
<span class="keyword">int</span><span class="special">),</span> <span class="keyword">int</span><span class="special">)</span></code>. This
|
||
is because <code class="computeroutput"><span class="identifier">bp</span><span class="special">::</span><span class="identifier">lexeme</span><span class="special">[]</span></code>
|
||
wraps its given parser in a new parser. <code class="computeroutput"><a class="link" href="../../boost/parser/merge.html" title="Global merge">merge[]</a></code>
|
||
does not. That's why, even though <code class="computeroutput"><span class="identifier">parser1</span></code>
|
||
and <code class="computeroutput"><span class="identifier">parser2</span></code> look so structurally
|
||
similar, they have different attributes.
|
||
</p>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h10"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation._globalname_alt__boost__parser__transform___code__phrase_role__identifier__transform__phrase__phrase_role__special_____phrase__phrase_role__identifier__f__phrase__phrase_role__special_______phrase___code___globalname_"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation._globalname_alt__boost__parser__transform___code__phrase_role__identifier__transform__phrase__phrase_role__special_____phrase__phrase_role__identifier__f__phrase__phrase_role__special_______phrase___code___globalname_"><code class="computeroutput">transform(f)[]</code></a>
|
||
</h5>
|
||
<p>
|
||
<code class="computeroutput">transform(f)[]</code>
|
||
is a directive that transforms the attribute of a parser using the given
|
||
function <code class="computeroutput"><span class="identifier">f</span></code>. For example:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">str_sum</span> <span class="special">=</span> <span class="special">[&](</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">s</span><span class="special">)</span> <span class="special">{</span>
|
||
<span class="keyword">int</span> <span class="identifier">retval</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
||
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">auto</span> <span class="identifier">ch</span> <span class="special">:</span> <span class="identifier">s</span><span class="special">)</span> <span class="special">{</span>
|
||
<span class="identifier">retval</span> <span class="special">+=</span> <span class="identifier">ch</span> <span class="special">-</span> <span class="char">'0'</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">return</span> <span class="identifier">retval</span><span class="special">;</span>
|
||
<span class="special">};</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">constexpr</span> <span class="keyword">auto</span> <span class="identifier">parser</span> <span class="special">=</span> <span class="special">+</span><span class="identifier">bp</span><span class="special">::</span><span class="identifier">char_</span><span class="special">;</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">str</span> <span class="special">=</span> <span class="string">"012345"</span><span class="special">;</span>
|
||
|
||
<span class="keyword">auto</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">str</span><span class="special">,</span> <span class="identifier">bp</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">str_sum</span><span class="special">)[</span><span class="identifier">parser</span><span class="special">]);</span>
|
||
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">result</span><span class="special">);</span>
|
||
<span class="identifier">assert</span><span class="special">(*</span><span class="identifier">result</span> <span class="special">==</span> <span class="number">15</span><span class="special">);</span>
|
||
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same_v</span><span class="special"><</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">result</span><span class="special">),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">>>);</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
<p>
|
||
Here, we have a function <code class="computeroutput"><span class="identifier">str_sum</span></code>
|
||
that we use for <code class="computeroutput"><span class="identifier">f</span></code>. It assumes
|
||
each character in the given <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||
<code class="computeroutput"><span class="identifier">s</span></code> is a digit, and returns
|
||
the sum of all the digits in <code class="computeroutput"><span class="identifier">s</span></code>.
|
||
Out parser <code class="computeroutput"><span class="identifier">parser</span></code> would normally
|
||
return a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>. However, since <code class="computeroutput"><span class="identifier">str_sum</span></code>
|
||
returns a different type — <code class="computeroutput"><span class="keyword">int</span></code>
|
||
— that is the attribute type of the full parser, <code class="computeroutput"><span class="identifier">bp</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">by_value_str_sum</span><span class="special">)[</span><span class="identifier">parser</span><span class="special">]</span></code>, as you can see from the <code class="computeroutput"><span class="keyword">static_assert</span></code>.
|
||
</p>
|
||
<p>
|
||
As is the case with attributes all throughout Boost.Parser, the attribute
|
||
passed to <code class="computeroutput"><span class="identifier">f</span></code> will be moved.
|
||
You can take it by <code class="computeroutput"><span class="keyword">const</span> <span class="special">&</span></code>,
|
||
<code class="computeroutput"><span class="special">&&</span></code>, or by value.
|
||
</p>
|
||
<p>
|
||
No distinction is made between parsers with and without an attribute, because
|
||
there is a Regular special no-attribute type that is generated by parsers
|
||
with no attribute. You may therefore write something like <code class="computeroutput">transform<span class="special">(</span><span class="identifier">f</span><span class="special">)[</span><a class="link" href="../../boost/parser/eps.html" title="Global eps">eps</a><span class="special">]</span></code>, and Boost.Parser will happily call <code class="computeroutput"><span class="identifier">f</span></code> with this special no-attribute type.
|
||
</p>
|
||
<h5>
|
||
<a name="boost_parser.tutorial.attribute_generation.h11"></a>
|
||
<span class="phrase"><a name="boost_parser.tutorial.attribute_generation.other_directives_that_affect_attribute_generation"></a></span><a class="link" href="attribute_generation.html#boost_parser.tutorial.attribute_generation.other_directives_that_affect_attribute_generation">Other
|
||
directives that affect attribute generation</a>
|
||
</h5>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/omit.html" title="Global omit">omit</a><span class="special">[</span><span class="identifier">p</span><span class="special">]</span></code>
|
||
disables attribute generation for the parser <code class="computeroutput"><span class="identifier">p</span></code>.
|
||
<code class="computeroutput"><a class="link" href="../../boost/parser/raw.html" title="Global raw">raw</a><span class="special">[</span><span class="identifier">p</span><span class="special">]</span></code>
|
||
changes the attribute from <code class="computeroutput"><span class="emphasis"><em><code class="literal">ATTR</code></em></span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code>
|
||
to a view that indicates the subrange of the input that was matched by <code class="computeroutput"><span class="identifier">p</span></code>. <code class="computeroutput"><a class="link" href="../../boost/parser/string_view.html" title="Global string_view">string_view</a><span class="special">[</span><span class="identifier">p</span><span class="special">]</span></code> is just
|
||
like <code class="computeroutput"><a class="link" href="../../boost/parser/raw.html" title="Global raw">raw</a><span class="special">[</span><span class="identifier">p</span><span class="special">]</span></code>,
|
||
except that it produces <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string_view</span></code>s.
|
||
See <a class="link" href="directives.html" title="Directives">Directives</a> for
|
||
details.
|
||
</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="combining_operations.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="the__parse____api.html"><img src="../../images/next.png" alt="Next"></a>
|
||
</div>
|
||
</body>
|
||
</html>
|