📄 common.hpp
字号:
if (keep) {
// adjust the length
length += std::distance((*i).value.begin(), (*i).value.end());
// move the child node
new_children.push_back(value_t());
swap(new_children.back(), *i);
keep = false;
}
else {
// ignore this child node
keep = true;
}
}
m = MatchT(length, new_children);
}
};
const node_parser_gen<infix_node_op> infix_node_d =
node_parser_gen<infix_node_op>();
struct discard_first_node_op
{
template <typename MatchT>
void operator()(MatchT& m) const
{
typedef typename MatchT::container_t container_t;
typedef typename MatchT::container_t::iterator iter_t;
typedef typename MatchT::container_t::value_type value_t;
using std::swap;
using boost::swap;
using boost::spirit::swap;
// copying the tree nodes is expensive, since it may copy a whole
// tree. swapping them is cheap, so swap the nodes we want into
// a new container of children, instead of saying
// m.trees.erase(m.trees.begin()) because, on a vector that will cause
// all the nodes afterwards to be copied into the previous position.
container_t new_children;
std::size_t length = 0;
std::size_t tree_size = m.trees.size();
// the discard_first_node_d[] make no sense for nodes with no subnodes
BOOST_SPIRIT_ASSERT(tree_size >= 1);
if (tree_size > 1) {
new_children.reserve(tree_size - 1);
iter_t i = m.trees.begin(), i_end = m.trees.end();
for (++i; i != i_end; ++i)
{
// adjust the length
length += std::distance((*i).value.begin(), (*i).value.end());
// move the child node
new_children.push_back(value_t());
swap(new_children.back(), *i);
}
}
else {
// if there was a tree and now there isn't any, insert an empty node
iter_t i = m.trees.begin();
// This isn't entirely correct, since the empty node will reference
// the end of the discarded node, but I currently don't see any way to
// get at the begin of the node following this subnode.
// This should be safe anyway because the it shouldn't get dereferenced
// under any circumstances.
typedef typename value_t::parse_node_t::iterator_t iterator_type;
iterator_type it = (*i).value.end();
new_children.push_back(
value_t(typename value_t::parse_node_t(it, it)));
}
m = MatchT(length, new_children);
}
};
const node_parser_gen<discard_first_node_op> discard_first_node_d =
node_parser_gen<discard_first_node_op>();
struct discard_last_node_op
{
template <typename MatchT>
void operator()(MatchT& m) const
{
typedef typename MatchT::container_t container_t;
typedef typename MatchT::container_t::iterator iter_t;
typedef typename MatchT::container_t::value_type value_t;
using std::swap;
using boost::swap;
using boost::spirit::swap;
// copying the tree nodes is expensive, since it may copy a whole
// tree. swapping them is cheap, so swap the nodes we want into
// a new container of children, instead of saying
// m.trees.erase(m.trees.begin()) because, on a vector that will cause
// all the nodes afterwards to be copied into the previous position.
container_t new_children;
std::size_t length = 0;
std::size_t tree_size = m.trees.size();
// the discard_last_node_d[] make no sense for nodes with no subnodes
BOOST_SPIRIT_ASSERT(tree_size >= 1);
if (tree_size > 1) {
m.trees.pop_back();
new_children.reserve(tree_size - 1);
iter_t i_end = m.trees.end();
for (iter_t i = m.trees.begin(); i != i_end; ++i)
{
// adjust the length
length += std::distance((*i).value.begin(), (*i).value.end());
// move the child node
new_children.push_back(value_t());
swap(new_children.back(), *i);
}
}
else {
// if there was a tree and now there isn't any, insert an empty node
iter_t i = m.trees.begin();
typedef typename value_t::parse_node_t::iterator_t iterator_type;
iterator_type it = (*i).value.begin();
new_children.push_back(
value_t(typename value_t::parse_node_t(it, it)));
}
m = MatchT(length, new_children);
}
};
const node_parser_gen<discard_last_node_op> discard_last_node_d =
node_parser_gen<discard_last_node_op>();
struct inner_node_op
{
template <typename MatchT>
void operator()(MatchT& m) const
{
typedef typename MatchT::container_t container_t;
typedef typename MatchT::container_t::iterator iter_t;
typedef typename MatchT::container_t::value_type value_t;
using std::swap;
using boost::swap;
using boost::spirit::swap;
// copying the tree nodes is expensive, since it may copy a whole
// tree. swapping them is cheap, so swap the nodes we want into
// a new container of children, instead of saying
// m.trees.erase(m.trees.begin()) because, on a vector that will cause
// all the nodes afterwards to be copied into the previous position.
container_t new_children;
std::size_t length = 0;
std::size_t tree_size = m.trees.size();
// the inner_node_d[] make no sense for nodes with less then 2 subnodes
BOOST_SPIRIT_ASSERT(tree_size >= 2);
if (tree_size > 2) {
m.trees.pop_back(); // erase the last element
new_children.reserve(tree_size - 1);
iter_t i = m.trees.begin(); // skip over the first element
iter_t i_end = m.trees.end();
for (++i; i != i_end; ++i)
{
// adjust the length
length += std::distance((*i).value.begin(), (*i).value.end());
// move the child node
new_children.push_back(value_t());
swap(new_children.back(), *i);
}
}
else {
// if there was a tree and now there isn't any, insert an empty node
iter_t i = m.trees.begin(); // skip over the first element
typedef typename value_t::parse_node_t::iterator_t iterator_type;
iterator_type it = (*++i).value.begin();
new_children.push_back(
value_t(typename value_t::parse_node_t(it, it)));
}
m = MatchT(length, new_children);
}
};
const node_parser_gen<inner_node_op> inner_node_d =
node_parser_gen<inner_node_op>();
//////////////////////////////////
// action_directive_parser and action_directive_parser_gen
// are meant to be used as a template to create directives that
// generate action classes. For example access_match and
// access_node. The ActionParserT template parameter must be
// a class that has an innter class called action that is templated
// on the parser type and the action type.
template <typename ActionParserT>
struct action_directive_parser_gen;
template <typename T, typename ActionParserT>
struct action_directive_parser
: public unary<T, parser<action_directive_parser<T, ActionParserT> > >
{
typedef action_directive_parser<T, ActionParserT> self_t;
typedef action_directive_parser_gen<ActionParserT> parser_generator_t;
typedef unary_parser_category parser_category_t;
// typedef action_directive_parser<T, ActionParserT> const &embed_t;
action_directive_parser(T const& a)
: unary<T, parser<action_directive_parser<T, ActionParserT> > >(a) {}
template <typename ScannerT>
typename parser_result<self_t, ScannerT>::type
parse(ScannerT const& scanner) const
{
return this->subject().parse(scanner);
}
template <typename ActionT>
typename ActionParserT::template action<action_directive_parser<T, ActionParserT>, ActionT>
operator[](ActionT const& actor) const
{
typedef typename
ActionParserT::template action<action_directive_parser, ActionT>
action_t;
return action_t(*this, actor);
}
};
//////////////////////////////////
template <typename ActionParserT>
struct action_directive_parser_gen
{
template <typename T>
struct result {
typedef action_directive_parser<T, ActionParserT> type;
};
template <typename T>
static action_directive_parser<T, ActionParserT>
generate(parser<T> const& s)
{
return action_directive_parser<T, ActionParserT>(s.derived());
}
template <typename T>
action_directive_parser<T, ActionParserT>
operator[](parser<T> const& s) const
{
return action_directive_parser<T, ActionParserT>(s.derived());
}
};
//////////////////////////////////
// Calls the attached action passing it the match from the parser
// and the first and last iterators
struct access_match_action
{
// inner template class to simulate template-template parameters
template <typename ParserT, typename ActionT>
struct action
: public unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >
{
typedef action_parser_category parser_category;
typedef action<ParserT, ActionT> self_t;
action( ParserT const& subject,
ActionT const& actor_);
template <typename ScannerT>
typename parser_result<self_t, ScannerT>::type
parse(ScannerT const& scanner) const;
ActionT const &predicate() const;
private:
ActionT actor;
};
};
//////////////////////////////////
template <typename ParserT, typename ActionT>
access_match_action::action<ParserT, ActionT>::action(
ParserT const& subject,
ActionT const& actor_)
: unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >(subject)
, actor(actor_)
{}
//////////////////////////////////
template <typename ParserT, typename ActionT>
template <typename ScannerT>
typename parser_result<access_match_action::action<ParserT, ActionT>, ScannerT>::type
access_match_action::action<ParserT, ActionT>::
parse(ScannerT const& scan) const
{
typedef typename ScannerT::iterator_t iterator_t;
typedef typename parser_result<self_t, ScannerT>::type result_t;
if (!scan.at_end())
{
iterator_t save = scan.first;
result_t hit = this->subject().parse(scan);
actor(hit, save, scan.first);
return hit;
}
return scan.no_match();
}
//////////////////////////////////
template <typename ParserT, typename ActionT>
ActionT const &access_match_action::action<ParserT, ActionT>::predicate() const
{
return actor;
}
//////////////////////////////////
const action_directive_parser_gen<access_match_action> access_match_d
= action_directive_parser_gen<access_match_action>();
//////////////////////////////////
// Calls the attached action passing it the node from the parser
// and the first and last iterators
struct access_node_action
{
// inner template class to simulate template-template parameters
template <typename ParserT, typename ActionT>
struct action
: public unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >
{
typedef action_parser_category parser_category;
typedef action<ParserT, ActionT> self_t;
action( ParserT const& subject,
ActionT const& actor_);
template <typename ScannerT>
typename parser_result<self_t, ScannerT>::type
parse(ScannerT const& scanner) const;
ActionT const &predicate() const;
private:
ActionT actor;
};
};
//////////////////////////////////
template <typename ParserT, typename ActionT>
access_node_action::action<ParserT, ActionT>::action(
ParserT const& subject,
ActionT const& actor_)
: unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >(subject)
, actor(actor_)
{}
//////////////////////////////////
template <typename ParserT, typename ActionT>
template <typename ScannerT>
typename parser_result<access_node_action::action<ParserT, ActionT>, ScannerT>::type
access_node_action::action<ParserT, ActionT>::
parse(ScannerT const& scan) const
{
typedef typename ScannerT::iterator_t iterator_t;
typedef typename parser_result<self_t, ScannerT>::type result_t;
if (!scan.at_end())
{
iterator_t save = scan.first;
result_t hit = this->subject().parse(scan);
if (hit && hit.trees.size() > 0)
actor(*hit.trees.begin(), save, scan.first);
return hit;
}
return scan.no_match();
}
//////////////////////////////////
template <typename ParserT, typename ActionT>
ActionT const &access_node_action::action<ParserT, ActionT>::predicate() const
{
return actor;
}
//////////////////////////////////
const action_directive_parser_gen<access_node_action> access_node_d
= action_directive_parser_gen<access_node_action>();
//////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// tree_parse_info
//
// Results returned by the tree parse functions:
//
// stop: points to the final parse position (i.e parsing
// processed the input up to this point).
//
// match: true if parsing is successful. This may be full:
// the parser consumed all the input, or partial:
// the parser consumed only a portion of the input.
//
// full: true when we have a full match (i.e the parser
// consumed all the input.
//
// length: The number of characters consumed by the parser.
// This is valid only if we have a successful match
// (either partial or full). A negative value means
// that the match is unsucessful.
//
// trees: Contains the root node(s) of the tree.
//
///////////////////////////////////////////////////////////////////////////////
template <
typename IteratorT = char const *,
typename NodeFactoryT = node_val_data_factory<nil_t>,
typename T = nil_t
>
struct tree_parse_info {
IteratorT stop;
bool match;
bool full;
std::size_t length;
typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees;
tree_parse_info()
: stop()
, match(false)
, full(false)
, length(0)
, trees()
{}
template <typename IteratorT2>
tree_parse_info(tree_parse_info<IteratorT2> const& pi)
: stop(pi.stop)
, match(pi.match)
, full(pi.full)
, length(pi.length)
, trees()
{
using std::swap;
using boost::swap;
using boost::spirit::swap;
// use auto_ptr like ownership for the trees data member
swap(trees, pi.trees);
}
tree_parse_info(
IteratorT stop_,
bool match_,
bool full_,
std::size_t length_,
typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees_)
: stop(stop_)
, match(match_)
, full(full_)
, length(length_)
, trees()
{
using std::swap;
using boost::swap;
using boost::spirit::swap;
// use auto_ptr like ownership for the trees data member
swap(trees, trees_);
}
};
}} // namespace boost::spirit
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -