2013-07-30 5 views
2

Я пытаюсь использовать Boost Дух, чтобы разобрать следующую грамматику: фраза: существительного глагола предложения конъюнкции предложениенеобработанного исключения при помощи Boost Духа для анализа грамматики

конъюнкция: «и»

существительное: "птицы" "кошки"

глагол: "летать" "мяу"

Разбор происходит успешно, когда грамматика содержит только существительное >> правило глагола. , когда грамматика изменена, чтобы включить предложение >> соединение >> правило предложения, и я поставлю недопустимый ввод, такой как «bird fly» вместо «birdfly». Я получаю необработанное исключение, когда программа запускается.

вот код, который модифицирован из примеров, найденных на повышающем доке

#define BOOST_VARIANT_MINIMIZE_SIZE 
#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/lex_lexertl.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/spirit/include/phoenix_statement.hpp> 
#include <boost/spirit/include/phoenix_container.hpp> 
#include <iostream> 
#include <string> 

using namespace boost::spirit; 
using namespace boost::spirit::ascii; 

template <typename Lexer> 
struct token_list : lex::lexer<Lexer> 
{ 
    token_list() 
    { 
     noun = "birds|cats";  
     verb = "fly|meow"; 
     conjunction = "and"; 

     this->self.add 
      (noun)   
      (verb) 
      (conjunction) 
     ; 
    } 
    lex::token_def<std::string> noun, verb, conjunction; 
}; 

template <typename Iterator> 
struct Grammar : qi::grammar<Iterator> 
{ 
    template <typename TokenDef> 
    Grammar(TokenDef const& tok) 
     : Grammar::base_type(sentence) 
    { 
     sentence = (tok.noun>>tok.verb) 
     | 
     (sentence>>tok.conjunction>>sentence)>>eoi 
    ; 
    } 
    qi::rule<Iterator> sentence; 
}; 

int main() 
{ 
typedef lex::lexertl::token<char const*, boost::mpl::vector<std::string>> token_type; 
typedef lex::lexertl::lexer<token_type> lexer_type; 
typedef token_list<lexer_type>::iterator_type iterator_type; 

    token_list<lexer_type> word_count;   
    Grammar<iterator_type> g (word_count); 

    std::string str = "birdsfly"; 
//std::string str = "birds fly"; this input caused unhandled exception 

    char const* first = str.c_str(); 
    char const* last = &first[str.size()]; 

    bool r = lex::tokenize_and_parse(first, last, word_count, g); 

    if (r) { 
     std::cout << "Parsing passed"<< "\n"; 
    } 
    else { 
     std::string rest(first, last); 
     std::cerr << "Parsing failed\n" << "stopped at: \"" 
        << rest << "\"\n"; 
    } 
    system("PAUSE"); 
    return 0; 
} 

ответ

2

Вы оставили рекурсию во второй ветви sentence правил.

sentence = sentence >> .... 

всегда будет отбывать наказание, так что вы увидите переток stackoverflow.

Я предлагаю писать правила, как, например:

sentence = 
     (tok.noun >> tok.verb) 
    >> *(tok.conjunction >> sentence) 
    >> qi::eoi 
    ; 

Теперь результат читает

g++ -Wall -pedantic -std=c++0x -g -O0 test.cpp -o test 
Parsing failed 
stopped at: " fly" 

(и неизбежного "ш: PAUSE: команда не найдена", конечно ...)

PS. Не using namespace пожалуйста. Вместо этого:

namespace qi = boost::spirit::qi; 
namespace lex = boost::spirit::lex; 

Вот очищены версия с некоторыми другими вещами удален/исправлено: http://coliru.stacked-crooked.com/view?id=1fb26ca3e8c207979eaaf4592c319316-e223fd4a885a77b520bbfe69dda8fb91

#define BOOST_VARIANT_MINIMIZE_SIZE 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/lex_lexertl.hpp> 
// #include <boost/spirit/include/phoenix.hpp> 
#include <iostream> 
#include <string> 

namespace qi = boost::spirit::qi; 
namespace lex = boost::spirit::lex; 

template <typename Lexer> 
struct token_list : lex::lexer<Lexer> 
{ 
    token_list() 
    { 
     noun  = "birds|cats";  
     verb  = "fly|meow"; 
     conjunction = "and"; 

     this->self.add 
      (noun)   
      (verb) 
      (conjunction) 
     ; 
    } 

    lex::token_def<std::string> noun, verb, conjunction; 
}; 

template <typename Iterator> 
struct Grammar : qi::grammar<Iterator> 
{ 
    template <typename TokenDef> 
    Grammar(TokenDef const& tok) : Grammar::base_type(sentence) 
    { 
     sentence = 
       (tok.noun >> tok.verb) 
      >> *(tok.conjunction >> sentence) 
      >> qi::eoi 
      ; 
    } 
    qi::rule<Iterator> sentence; 
}; 

int main() 
{ 
    typedef std::string::const_iterator It; 
    typedef lex::lexertl::token<It, boost::mpl::vector<std::string>> token_type; 
    typedef lex::lexertl::lexer<token_type> lexer_type; 
    typedef token_list<lexer_type>::iterator_type iterator_type; 

    token_list<lexer_type> word_count;   
    Grammar<iterator_type> g(word_count); 

    //std::string str = "birdsfly"; 
    const std::string str = "birds fly"; 

    It first = str.begin(); 
    It last = str.end(); 

    bool r = lex::tokenize_and_parse(first, last, word_count, g); 

    if (r) { 
     std::cout << "Parsing passed"<< "\n"; 
    } 
    else { 
     std::string rest(first, last); 
     std::cerr << "Parsing failed\n" << "stopped at: \"" << rest << "\"\n"; 
    } 
} 
+1

sehe, гуру SO.com Дух в этом снова :) – rubenvb

+0

@cv_and_he я считал, он» вернемся к этому, когда будете готовы. Давайте не будем нажимать OP - он просто пропустит детали и не поймет, если мы заполним детали для него. ** Редактировать ** Спасибо в любом случае за то, что выкопали ** [соответствующую ссылку] (http://stackoverflow.com/questions/13361519/troubles-with-boostspiritlex-whitespace/13367439#13367439) ** в случае, если он хочет возглавить над. Извините, если я предположил, что ваш комментарий был нежелательным. Приветствую. – sehe

+0

Пожалуйста, прекратите стирание истории. – rubenvb

 Смежные вопросы

  • Нет связанных вопросов^_^