Разобрать выражение time_period с помощью Boost :: Spirit

Мне нужно проанализировать следующее выражение EBNF с Boost :: Spirit.

period ::= date_part [time_part] , date_part [time_part]
time_part ::= hours:minutes[:seconds]
date_part ::= day.month.year

Например, 10.06.2014 10:00:15, 11.07.2014, Я сделал свою грамматику двумя способами, но не могу получить рабочий пример.

1) Первая попытка

    struct Parser: grammar<std::string::const_iterator, space_type>
{
Parser(): Parser::base_type(datetime_)
{
using boost::spirit::int_;

using boost::spirit::qi::_1;
using boost::spirit::qi::_2;

using boost::spirit::qi::_val;

datetime_ =
(date_ >> time_)
[
_val =
phoenix::construct<ptime>
(
date(_1[2]), _1[1], _1[0]),
hours(_2[0]) + minutes(_2[1]) + seconds[_2[0]]
)
|
_val =
phoenix::construct<ptime>
(
date(_1[2]), _1[1], _1[0]),
seconds(0)
)
];

date_ %= int_ % '.';
time_ %= int_ % ':';

BOOST_SPIRIT_DEBUG_NODE(datetime_);
BOOST_SPIRIT_DEBUG_NODE(date_);
BOOST_SPIRIT_DEBUG_NODE(time_);
}

rule<std::string::const_iterator, std::vector<int>(), space_type> date_, time_;
rule<std::string::const_iterator, ptime(), space_type> datetime_;
}

Parser parser;
std::string strTest("10.06.2014 10:00:15, 11.07.2014");

std::string::const_iterator it_begin(strTest.begin());
std::string::const_iterator it_end(strTest.end());

bool result = phrase_parse(it_begin, it_end, parser, space);

Ошибки:

/media/Data/Projects/Qt/Planner/parser.h:108: ошибка: no matching function for call to 'boost::gregorian::date::date(boost::phoenix::detail::make_index_composite<boost::phoenix::actor<boost::spirit::argument<0> >, int>::type)'

И так далее. Я не могу бросить boost::spirit::argument<0> в int или же date::years_type, я пытался date((int)_1[2]), (int)_1[1], (int)_1[0])) а также dynamic_cast<int>(_1[2]), но безуспешно (.

2) Вторая попытка

    struct Parser: grammar<std::string::const_itearator, space_type>
{
Parser(ConditionTree& a_lTree):
Parser::base_type(time_period_),
m_lTree(a_lTree)
{
using boost::spirit::int_;

using boost::spirit::qi::_1;
using boost::spirit::qi::_2;
using boost::spirit::qi::_3;
using boost::spirit::qi::_4;
using boost::spirit::qi::_5;
using boost::spirit::qi::_val;

time_period_ = ( datetime_ > ',' > datetime_ ) [ _val = phoenix::construct<time_period>((int)_1, (int)_3) ];

datetime_ = (date_ >> time_duration_) [ _val = phoenix::construct<ptime>((int)_1, (int)_2) | _val = phoenix::construct<ptime>((int)_1, seconds(0)) ] ;

date_ = (int_ > '.' > int_ > '.' > int_) [ _val = phoenix::construct<date>((int)_5, (int)_3, (int)_1) ];

time_duration_ = (int_ > ':' > int_ > ':' > int_) [ _val = phoenix::construct<time_duration>((int)_1, (int)_3, (int)_5, 0)];

BOOST_SPIRIT_DEBUG_NODE(time_period_);
BOOST_SPIRIT_DEBUG_NODE(datetime_);
BOOST_SPIRIT_DEBUG_NODE(date_);
BOOST_SPIRIT_DEBUG_NODE(time_duration_);

}

rule<std::string::const_itarator, time_period(), space_type> time_period_;
rule<std::string::const_itarator, ptime(), space_type> datetime_;
rule<std::string::const_itarator, date(), space_type> date_;
rule<std::string::const_itarator, time_duration(), space_type> time_duration_;

ConditionTree& m_lTree;
};

Ошибка:

/media/Data/Projects/Qt/Planner/parser.h:114: ошибка: invalid cast from type 'const _1_type {aka const boost::phoenix::actor<boost::spirit::argument<0> >}' to type 'int'

Почему я не могу разыграть boost :: spirit :: аргумент<0> в инт ????

3

Решение

Лучший вопрос, почему вы могли бы привести тип заполнителя к конкретному типу примитива?

Заполнитель является ленивый актер только, так что вы должны использовать Феникс cast_ разыграть, если вообще (намекэто не нужно) Жить на Колиру

Выход

<period_>
<try>10.06.2014 10:00:15,</try>
<date_>
<try>10.06.2014 10:00:15,</try>
<success> 10:00:15, 11.07.201</success>
<attributes>[[10, 6, 2014]]</attributes>
</date_>
<time_>
<try> 10:00:15, 11.07.201</try>
<success>, 11.07.2014</success>
<attributes>[[10, 0, 15]]</attributes>
</time_>
<date_>
<try> 11.07.2014</try>
<success></success>
<attributes>[[11, 7, 2014]]</attributes>
</date_>
<time_>
<try></try>
<fail/>
</time_>
<success></success>
<attributes>[[[[10, 6, 2014], [10, 0, 15]], [[11, 7, 2014], [empty]]]]</attributes>
</period_>
Parse success

Полный образец

#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi  = boost::spirit::qi;
namespace phx = boost::phoenix;

namespace Ast {
using boost::optional;
struct date { unsigned day, month, year; };
struct time { unsigned hours, minutes, seconds; };
struct date_time { date date_part; optional<time> time_part; };

struct period { date_time start, end; };
}

BOOST_FUSION_ADAPT_STRUCT(Ast::date, (unsigned,day)(unsigned,month)(unsigned,year))
BOOST_FUSION_ADAPT_STRUCT(Ast::time, (unsigned,hours)(unsigned,minutes)(unsigned,seconds))
BOOST_FUSION_ADAPT_STRUCT(Ast::date_time, (Ast::date,date_part)(Ast::optional<Ast::time>, time_part))
BOOST_FUSION_ADAPT_STRUCT(Ast::period, (Ast::date_time,start)(Ast::date_time,end))

template <typename Iterator>
struct Parser : qi::grammar<Iterator, Ast::period(), qi::space_type>
{
int test;
Parser() : Parser::base_type(period_)
{
using namespace qi;

static const int_parser<unsigned, 10, 2, 2> _2digit = {};
static const int_parser<unsigned, 10, 4, 4> _4digit = {};

time_      = _2digit >> ":" >> _2digit >> ":" >> _2digit;
date_      = _2digit >> "." >> _2digit >> "." >> _4digit;
date_time_ = date_ >> -time_;
period_    = date_time_ >> "," >> date_time_;

BOOST_SPIRIT_DEBUG_NODES((period_)(time_)(date_))
}

private:
qi::rule<Iterator, Ast::period(),    qi::space_type> period_;
qi::rule<Iterator, Ast::date(),      qi::space_type> date_;
qi::rule<Iterator, Ast::time(),      qi::space_type> time_;
qi::rule<Iterator, Ast::date_time(), qi::space_type> date_time_;
};int main()
{
using It = std::string::const_iterator;

Parser<It> parser;
std::string input("10.06.2014 10:00:15, 11.07.2014");

It f(input.begin()), l(input.end());

Ast::period parsed;
bool ok = qi::phrase_parse(f, l, parser, qi::space, parsed);

if (ok)
{
std::cout << "Parse success\n";
}
else
{
std::cout << "Parse failed\n";
}

if (f!=l)
std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
}
1

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector