Estoy usando QI y Phoenix, y quiero escribir una pequeña gramática que devuelva 4 bools que se usarán como argumentos para una llamada de función dentro de una acción semántica.Boost :: Spirit :: Qi. ¿Cómo convertir expresiones de analizador inline en gramáticas independientes y cómo descomprimir las tuplas generadas por ellas?
que tienen varias funciones que necesitan esas cosas, y hasta ahora han utilizado este enfoque:
(qi::_bool >> qi::_bool >> qi::_bool >> qi::_bool)
[px::bind(&Bool4Function, spirit::_val, spirit::_1, spirit::_2, spirit::_3, spirit::_4)]
y aunque está bien por sí mismo, utilizando por todo el lugar es simplemente feo y confuso, incluso con 'usar' las partes del espacio de nombres.
Es por eso que quería extraer esta expresión en una gramática independiente.
Así que probamos este (el crédito va a Ildjarn para el banco de pruebas):
///// grammar implementation /////
#include <boost/fusion/include/vector10.hpp>
#include <boost/spirit/include/qi_bool.hpp>
#include <boost/spirit/include/qi_char_.hpp>
#include <boost/spirit/include/qi_grammar.hpp>
#include <boost/spirit/include/qi_operator.hpp>
#include <boost/spirit/include/qi_rule.hpp>
#include <boost/spirit/include/qi_string.hpp>
struct FourBools : boost::spirit::qi::grammar<
char const*,
boost::fusion::vector4<bool, bool, bool, bool>()
>
{
typedef boost::fusion::vector4<bool, bool, bool, bool> attribute_type;
FourBools() : base_type(start_)
{
using boost::spirit::bool_;
start_
= "4bools:"
>> bool_ >> ','
>> bool_ >> ','
>> bool_ >> ','
>> bool_ >> ';'
;
}
private:
boost::spirit::qi::rule<
base_type::iterator_type,
base_type::sig_type
> start_;
};
FourBools const fourBools;
///// demonstration of use /////
#include <string>
#include <ios>
#include <iostream>
#include <boost/fusion/include/at_c.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/qi_action.hpp>
#include <boost/spirit/include/qi_parse.hpp>
void noDice(bool a, bool b, bool c, bool d)
{
}
void worksFine(boost::fusion::vector4<bool, bool, bool, bool> a)
{
}
int main()
{
namespace phx = boost::phoenix;
namespace spirit = boost::spirit;
std::string const input("4bools:true,true,true,false;");
char const* first = input.c_str();
char const* const last = first + input.size();
bool const success = spirit::qi::parse(
first, last,
fourBools[phx::bind(&noDice, spirit::_1)]
);
if (!success)
std::cout << "parse() failed\n";
else if (first != last)
std::cout << "didn't consume all input\n";
std::cout.flush();
}
Eso no se compila a menos fourBools[phx::bind(&noDice, spirit::_1)]
se sustituye con fourBools[phx::bind(&worksFine, spirit::_1)]
.
Eso significa que mi problema es desempacar los argumentos para que coincidan con la firma de la función que se llamará, ya que el número de argumentos difiere en el nivel de firma (una tupla de cuatro bools, contra cuatro bools).
¿Es posible desempaquetar usando marcadores de posición de fénix directamente, en lugar de escribir envoltorios que traducen tuplas en argumentos individuales para mis funciones existentes que los necesitan por separado? Si lo es, ¿cuál sería la sintaxis para eso? Después de todo, una versión en línea como (qi::_bool >> qi::_bool >> qi::_bool >> qi::_bool)
funciona bien cuando está 'desempaquetada' por marcadores de posición spirit::_1 - spirit::_4,
.
Eso me da la impresión de que esta versión también devuelve una tupla y, de alguna manera, es incompatible con el enfoque anterior, a diferencia de una gramática que devuelve una.
¿Cómo manejo esto?
Comentarios como este probablemente estén mal visto, pero tengo que estar contento de ver este tipo de código fuera de mi pecho. Me siento muy sucio al lado, es muy motivador, ni siquiera sabía la mitad de las cosas enumeradas y pensé que ya estaba mejorando. De todos modos, incluiré un repro mañana, si todavía no funciona después de analizar a fondo su publicación. – Erius
@Erius: -] Si terminas publicando una reprografía, publica un comentario sobre esta respuesta, por lo que recibiré un mensaje en mi bandeja de entrada de SO, de lo contrario, probablemente no veré tu edición. – ildjarn
Hecho, gracias de nuevo. – Erius