c++ - ¿Es posible volver a utilizar la gramática boost:: spirit:: qi en otra definición gramatical?
boost-spirit boost-spirit-qi (1)
¿Es posible reutilizar boost::spirit:qi
grammar en otra gramática (por regla general, por ejemplo)?
Por ejemplo, si defino una gramática para analizar una línea de texto en una estructura con dirección de calle.
template< typename iter >
struct address_grammar : qi::grammar< iter, address() >
{
...
qi::rule< iter, std::string() > street_name;
qi::rule< iter, std::string() > street_number;
qi::rule< iter, address() > address_;
}
Me gustaría reutilizar esa gramática en otras dos gramáticas, por ejemplo, una podría ser para analizar un vector de direcciones almacenadas en un archivo. Otra reutilización podría ser en una estructura más compleja donde uno de los campos es esta estructura de dirección de la calle.
template< typename iter >
struct company_grammar : qi::grammar< iter, company() >
{
...
qi::rule< iter, std::string() > comp_name;
// can I reuse the address grammar somehow here ???
qi::rule< iter, company() > company;
}
En lugar de definir toda la gramática en un solo lugar, estoy pensando en dividirla en bloques reutilizables más pequeños, está bien si están dentro de un archivo de encabezado. Mis estructuras de datos son un poco más complejas (un par de campos dentro de struct con una lista de otras estructuras, etc.) así que no quiero ponerlo en una sola gramática.
¿Es posible reutilizar boost::spirit::qi
grammar de esta manera?
EDITAR: Pensando en eso, ¿simplemente defino qi::rule
s en un espacio de nombres y luego reúno una gramática de las reglas que necesito?
Por supuesto que puede. En su caso, simplemente ponga address_grammar<iter> address_;
en tu código
Déjame mostrarte otro ejemplo. Puede encontrar un código compilable aquí: http://ideone.com/GW4jO (consulte también a continuación)
AFAIK, a diferencia de qi :: gramática, qi :: rule es difícil de reutilizar.
Muestra completa
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
struct Date {
int year, month, day;
};
struct Time {
int hour, minute, second;
};
BOOST_FUSION_ADAPT_STRUCT(
Date,
(int, year)
(int, month)
(int, day)
)
BOOST_FUSION_ADAPT_STRUCT(
Time,
(int, hour)
(int, minute)
(int, second)
)
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
typedef std::string::const_iterator Iterator;
class DateParser:
public qi::grammar < Iterator, Date() > {
qi::rule < Iterator, Date() > main;
public:
DateParser(): base_type(main) {
main %= qi::int_ >> ''-'' >> // Year
qi::int_ >> ''-'' >> // Month
qi::int_; // Day
}
};
class TimeParser:
public qi::grammar < Iterator, Time() > {
qi::rule < Iterator, Time() > main;
public:
TimeParser(): base_type(main) {
main %= qi::int_ >> '':'' >> // Hour
qi::int_ >> '':'' >> // Minute
qi::int_; // Second
}
};
class DateTimeParser:
public qi::grammar < Iterator, boost::variant<Date, Time>() > {
qi::rule < Iterator, boost::variant<Date, Time>()> main;
public:
DateTimeParser(): base_type(main) {
main %= date_parser | time_parser;
}
DateParser date_parser;
TimeParser time_parser;
};
#include<iostream>
#include<cstdio>
struct Printer : public boost::static_visitor<> {
void operator()(Date a) const {
printf("Year: %d, Month: %d, Day: %d/n", a.year, a.month, a.day);
}
void operator()(Time a) const {
printf("Hour: %d, Minute: %d, Second: %d/n", a.hour, a.minute, a.second);
}
};
int main() {
std::string s;
std::getline(std::cin, s);
Iterator beg = s.begin(), end = s.end();
boost::variant<Date, Time> ret;
phrase_parse(beg, end, DateTimeParser(), ascii::space, ret);
if (beg != end)
puts("Parse failed.");
else
boost::apply_visitor(Printer(), ret);
}