Pergunta

Eu não estou sendo capaz de descobrir o que está errado com o meu código. modelos de impulso estão fazendo-me louco! Eu não posso fazer cara ou coroa para fora de tudo isso, então eu só tinha de perguntar.

O que há de errado com isso?

#include <iostream>
#include <boost/lambda/lambda.hpp>
#include <boost/spirit/include/qi.hpp>

void parsePathTest(const std::string &path)
{
    namespace lambda = boost::lambda;
    using namespace boost::spirit;

    const std::string permitted = "._\\-#@a-zA-Z0-9";
    const std::string physicalPermitted = permitted + "/\\\\";
    const std::string archivedPermitted = permitted + ":{}";

    std::string physical,archived;

    // avoids non-const reference to rvalue
    std::string::const_iterator begin = path.begin(),end = path.end();

    // splits a string like "some/nice-path/while_checking:permitted#symbols.bin"
    // as physical = "some/nice-path/while_checking"
    // and archived = "permitted#symbols.bin" (if this portion exists)
    // I could barely find out the type for this expression
    auto expr
        =   ( +char_(physicalPermitted) ) [lambda::var(physical) = lambda::_1]
            >> -(
                    ':'
                    >> (
                           +char_(archivedPermitted) [lambda::var(archived) = lambda::_1]
                       )
                )
        ;

    // the error occurs in a template instantiated from here
    qi::parse(begin,end,expr);

    std::cout << physical << '\n' << archived << '\n';
}

O número de erros é imenso; Gostaria de sugerir as pessoas que querem ajudar a compilar esta em seu on (confie em mim, colando aqui é impraticável). Eu estou usando a versão mais recente TDM-GCC (GCC 4.4.1) e aumentar a versão 1.39.00.

Como um bônus, eu gostaria de pedir mais duas coisas: se a nova funcionalidade static_assert do C ++ 0x vai ajudar a aumentar neste sentido, e se a implementação tenho citado acima é uma boa idéia, ou se eu deveria usar biblioteca de Cordas Algoritmos de impulso. Seria o último provavelmente dar um desempenho muito melhor?

Graças.

- edição

O exemplo a seguir muito mínima falha no início com exatamente o mesmo erro que o código acima.

#include <iostream>
#include <boost/spirit/include/qi.hpp>

int main()
{
    using namespace boost::spirit;

    std::string str = "sample";
    std::string::const_iterator begin(str.begin()), end(str.end());

    auto expr
        =   ( +char_("a-zA-Z") )
        ;

    // the error occurs in a template instantiated from here
    if (qi::parse(begin,end,expr))
    {
        std::cout << "[+] Parsed!\n";
    }
    else
    {
        std::cout << "[-] Parsing failed.\n";
    }

    return 0;
}

- edição 2

Eu ainda não sei por que não funcionou na minha versão antiga do Impulso (1,39), mas a atualização para impulsionar 1,42 resolveu o problema. Os seguintes compila código e funciona perfeitamente com reforço de 1,42:

#include <iostream>
#include <boost/spirit/include/qi.hpp>

int main()
{
    using namespace boost::spirit;

    std::string str = "sample";
    std::string::const_iterator begin(str.begin()), end(str.end());

    auto expr
        =   ( +qi::char_("a-zA-Z") ) // notice this line; char_ is not part of 
                                     // boost::spirit anymore (or maybe I didn't 
                                     // include the right headers, but, regardless, 
                                     // khaiser said I should use qi::char_, so here 
                                     // it goes)
        ;

    // the error occurs in a template instantiated from here
    if (qi::parse(begin,end,expr))
    {
        std::cout << "[+] Parsed!\n";
    }
    else
    {
        std::cout << "[-] Parsing failed.\n";
    }

    return 0;
}

Obrigado pelas dicas, hkaiser.

Foi útil?

Solução

Várias observações: a) não usar a versão beta Espírito V2 distribuído com impulso v1.39 e V1.40. Use no mínimo Espírito V2.1 (como divulgado com v1.41 Boost) em vez disso, uma vez que contém um muito de correções de bugs e melhorias de desempenho (ambos, tempo de compilação e desempenho de tempo de execução). Se você não pode alternar versões impulso, leia aqui para saber como proceder. b) Tente evitar o uso boost :: lambda ou boost :: bind com o Espírito v2.x. Sim, eu sei, os médicos dizem que funciona, mas você tem que saber o que está fazendo. Use expressões boost :: phoenix vez. Espírito 'sabe' sobre Phoenix, o que torna a escrita ações semânticas mais fácil. Se você usar Phoenix, seu código será parecido com:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

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

std::string physical, archived;  
auto expr 
    =   ( +char_(physicalPermitted) ) [phoenix::ref(physical) = qi::_1] 
    >> -( 
            ':' 
            >> ( +char_(archivedPermitted) )[phoenix::ref(archived) = qi::_1] 
        ) 
    ; 

Mas o seu analisador geral vai ficar ainda mais simples se você utilizar do Espírito built-in regras de propagação de atributos:

std::string physical;
boost::optional<std::string> archived;  

qi::parse(begin, end, 
    +qi::char_(physicalPermitted) >> -(':' >> +qi::char_(archivedPermitted)),
    physical, archived);

i. há necessidade de ter ações semânticas em tudo. Se precisar de mais informações sobre a manipulação de atributo, consulte a série de artigos sobre o Magic of Atributos no site do Espírito.

Editar:

Quanto à sua static_assert pergunta: sim static_assert, pode melhorar mensagens de erro, pois ele pode ser usado para erros do compilador gatilho o mais cedo possível. Na verdade, o Espírito usa esta técnica extensivamente já. Mas não é possível proteger o usuário de obter esses enormes mensagens de erro em todos os casos, mas apenas para os erros do usuário o programador não esperava. Somente conceitos (que, infelizmente, não fazê-lo para o novo padrão C ++) poderia ter sido usado geralmente para reduzir teh tamanho das mensagens de erro.

Quanto à pergunta de Cordas Algoritmos do seu Boost: certamente é possível utilizar esta biblioteca para tarefas simples como a sua. Você pode até ser melhor usar Boost.Tokenizer (se tudo que você precisa é dividir a seqüência de entrada na ':'). O desempenho do Espírito deve ser comparável ao desempenho correspondente dos algoritmos de cadeia, mas isso certamente depende do código que você vai escrever. Se você assumir que o algoritmo de corda utilizados exigirá uma passagem sobre os dados de cadeia de entrada, em seguida, o Espírito não será mais rápido (como ele está fazendo uma passagem bem).

Nem os algoritmos de corda impulso nem Boost Tokenizer pode lhe dar a verificação dos caracteres casada. Sua gramática Espírito corresponde apenas os caracteres que você especificadas nas classes de personagens. Então, se você precisa esta correspondência / verificação, você deve usar um Espírito ou Boost Regex.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top