Aumentar los problemas del patrón de espíritu

6 minutos de lectura

Aumentar los problemas del patron de espiritu
pantuflas sexy69

Tengo problemas con los patrones de impulso de espíritu.

Necesito analizar un archivo como ese:

ROW int
int [int, int]
int [int, int]
...

Puedo analizarlo sin problemas (gracias a stackoverflow;) solo si agrego un ‘_’ después del primer int.

De hecho, creo que el patrón se come el final de la línea después del primer int, por lo que el primero y el segundo (en la segunda línea) se ven como un solo int. No entiendo cómo mantener eol pero comer espacios. He encontrado ejemplos para usar un analizador personalizado como aquí y aquí.

Probé qi::blank, analizador personalizado con una sola regla encendida (‘ ‘) No importa qué patrón use, el espacio y el eol siempre se comen.

Mi gramática es:

una línea:

struct rowType
{
    unsigned int number;
    std::list<unsigned int> list;
};

el problema completo almacenado en una estructura:

struct problemType
{
    unsigned int ROW;
    std::vector<rowType> rows;
};

el analizador de filas:

template<typename Iterator>
struct row_parser : qi::grammar<Iterator, rowType(), qi::space_type>
{
    row_parser() : row_parser::base_type(start)
    {

        list="[" >> -(qi::int_ % ',') >> ']';
        start = qi::int_ >> list;
    }

    qi::rule<Iterator, rowType(), qi::space_type> start;
    qi::rule<Iterator, std::list<unsigned int>(), qi::space_type> list;
};

y el analizador de problemas:

template<typename Iterator>
struct problem_parser : qi::grammar<Iterator,problemType(),qi::space_type>
{

    problem_parser() : problem_parser::base_type(start)
    {
        using boost::phoenix::bind;
        using qi::lit;

        start = qi::int_ >> lit('_') >> +(row);

        //BOOST_SPIRIT_DEBUG_NODE(start);
    }

    qi::rule<Iterator, problemType(),qi::space_type> start;
    row_parser<Iterator> row;
};

Y lo uso así:

main() {
static const problem_parser<spirit::multi_pass<base_iterator_type> > p;
...
spirit::qi::phrase_parse(first, last ,
            p,
            qi::space,
            pb);
}

Por supuesto, el qi::space es mi problema, y ​​​​una forma de resolver mi problema sería no usar un patrón, pero frase_parse requiere uno, y luego mi analizador requiere uno.

Estoy atascado desde hace algunas horas… Creo que es algo obvio que no he entendido bien.

Gracias por tu ayuda.

1647577267 532 Aumentar los problemas del patron de espiritu
seje

En general, las siguientes directivas son útiles para inhibir/cambiar saltadores a mitad de la gramática:

  • qi::lexeme [ p ]
    que inhibe un patrón, por ejemplo, si desea asegurarse de analizar un identificador sin saltos internos) – consulte también no_skip para comparacion

  • qi::raw [ p ]
    que analiza como siempre, incluidos los saltos, pero devuelve el rango de iterador sin procesar de la secuencia de origen coincidente (incluidas las posiciones omitidas)

  • qi::no_skip [ p ]
    Inhibición de saltos sin salto previo (creé un ejemplo mínimo para demostrar la diferencia aquí: Boost Spirit lexema vs no_skip)

  • qi::skip(s) [ p ]
    que sustituye al patrón por otro patrón s en conjunto (tenga en cuenta que debe usar correctamente declarado qi::rule<> instancias dentro de tal skip[] cláusula)

donde p es cualquier expresión del analizador.

Solución específica

Tu problema, como ya sabes, puede ser que qi::space come todos espacio en blanco. No puedo saber qué es lo que está mal en su gramática (ya que no muestra la gramática completa ni la entrada relevante).

Por lo tanto, esto es lo que escribiría. Nota

  • el uso de qi::eol para explícitamente requieren saltos de línea en ubicaciones específicas
  • el uso de qi::blank como patrón (sin incluir eol)
  • por brevedad combiné las gramáticas

Código:

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

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

struct rowType {
    unsigned int number;
    std::list<unsigned int> list;
};

struct problemType {
    unsigned int ROW;
    std::vector<rowType> rows;
};

BOOST_FUSION_ADAPT_STRUCT(rowType, (unsigned int, number)(std::list<unsigned int>, list))
BOOST_FUSION_ADAPT_STRUCT(problemType, (unsigned int, ROW)(std::vector<rowType>, rows))

template<typename Iterator>
struct problem_parser : qi::grammar<Iterator,problemType(),qi::blank_type>
{
    problem_parser() : problem_parser::base_type(problem)
    {
        using namespace qi;
        list="[" >> -(int_ % ',') >> ']';
        row     = int_ >> list >> eol;
        problem = "ROW" >> int_ >> eol >> +row;

        BOOST_SPIRIT_DEBUG_NODES((problem)(row)(list));
    }

    qi::rule<Iterator, problemType()            , qi::blank_type> problem;
    qi::rule<Iterator, rowType()                , qi::blank_type> row;
    qi::rule<Iterator, std::list<unsigned int>(), qi::blank_type> list;
};

int main()
{
    const std::string input = 
        "ROW 1\n"
        "2 [3, 4]\n"
        "5 [6, 7]\n";

    auto f = begin(input), l = end(input);

    problem_parser<std::string::const_iterator> p;
    problemType data;

    bool ok = qi::phrase_parse(f, l, p, qi::blank, data);

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

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

Si realmente no quería requerir saltos de línea:

template<typename Iterator>
struct problem_parser : qi::grammar<Iterator,problemType(),qi::space_type>
{
    problem_parser() : problem_parser::base_type(problem)
    {
        using namespace qi;
        list="[" >> -(int_ % ',') >> ']';
        row     = int_ >> list;
        problem = "ROW" >> int_ >> +row;

        BOOST_SPIRIT_DEBUG_NODES((problem)(row)(list));
    }

    qi::rule<Iterator, problemType()            , qi::space_type> problem;
    qi::rule<Iterator, rowType()                , qi::space_type> row;
    qi::rule<Iterator, std::list<unsigned int>(), qi::space_type> list;
};

int main()
{
    const std::string input = 
        "ROW 1 " // NOTE whitespace, obviously required!
        "2 [3, 4]"
        "5 [6, 7]";

    auto f = begin(input), l = end(input);

    problem_parser<std::string::const_iterator> p;
    problemType data;

    bool ok = qi::phrase_parse(f, l, p, qi::space, data);

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

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

Actualizar

En respuesta al comentario: aquí hay un fragmento que muestra cómo leer la entrada de un archivo. Esto fue probado y funciona bien para mí:

std::ifstream ifs("input.txt"/*, std::ios::binary*/);
ifs.unsetf(std::ios::skipws);

boost::spirit::istream_iterator f(ifs), l;

problem_parser<boost::spirit::istream_iterator> p;

  • Ok, gracias (otra vez). Funciona con una cadena como const std::string input = “ROW 7\n” “1 [1] [1,2]\n” “3 [1]\n” “4 [1, 3]\n” “2 [1, 3]\n” “6 [2, 3] [4]\n” “5 [4, 6] [1]\n” “7 [1, 5] [2]\n”; pero no si lo leo desde un archivo con el analizador multipaso. No entiendo por qué. ¿Alguna idea?

    – sexyslippers69

    13 de junio de 2013 a las 11:36

  • Probablemente se olvidó de configurar std::ios::binary y/o std::noskipws en el flujo de archivos? Otra solución es adaptar varias pasadas std::istreambuf_iterator<> en lugar de std::istream_iterator<> IIRC

    – seje

    13 de junio de 2013 a las 11:43

  • Actualicé la respuesta para incluir un fragmento que muestra cómo leer un archivo ("input.txt") con el mismo analizador. Ver en Actualizar El fondo.

    – seje

    13 de junio de 2013 a las 11:49

  • @sehe, gracias por el ejemplo de transmisión; el primero que funcionó para mí.

    – usuario23573

    7 mayo 2015 a las 10:47

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad