J'utilise Boost.Spirit (Boost 1.59.0) pour essayer de parser, progressivement, un fichier d'échecs PGN. (En ce moment je teste juste une simple partie, sans les en-têtes).
Mais je ne parviens pas à comprendre pourquoi ma grammaire pose problème : les messages d'erreur sont indéchiffrables pour moi.

Voici mon code source (pour l'instant dans un seul fichier) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
 
namespace loloof64 {
 
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;
    namespace phoenix = boost::phoenix;
 
    /*struct pgn_tag {
        std::string key;
        std::string value;
    };*/
 
    struct game_move {
        unsigned move_number;
        std::string move_turn;
        std::string white_move;
        std::string black_move;
        std::string result;
    };
 
}
 
/*
BOOST_FUSION_ADAPT_STRUCT(
    loloof64::pgn_tag,
    (std::string, key),
    (std::string, value)
)
*/
 
BOOST_FUSION_ADAPT_STRUCT(
    loloof64::game_move,
    (unsigned, move_number),
    (std::string, move_turn),
    (std::string, white_move),
    (std::string, black_move),
    (std::string, result)
)
 
 
namespace loloof64 {
    template <typename Iterator>
    struct pgn_parser : qi::grammar<Iterator, std::vector<game_move>, qi::unused_type>
    {
        pgn_parser() : pgn_parser::base_type(game)
        {
            using qi::lexeme;
            using ascii::char_;
            using qi::uint_;
            using qi::alnum;
            using qi::space;
            using qi::omit;
            using qi::eol;
            using qi::lit;
 
 
            /*
            quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
 
            tag %=
                '['
                >> +alnum
                >> omit[+space]
                >> quoted_string
                >> ']'
                >> omit[+eol]
                ;
 
            header %= +tag;
            */
 
            move_turn %= lit(".") | lit("...");
 
            regular_move %= lexeme[-char_("NBRQK") >> -char_("a-h1-8") >> -'x' >> char_("a-h") >> char_("1-8")
                                >> -(('=' >> char_("NBRQ")) | ('e' >> '.' >> 'p' >> '.'))];
            castle_move %= lit("O-O") | lit("O-O-O");
            single_move %= (regular_move | castle_move) >> -('+' | '#');
 
            full_move %=
                uint_
                >> move_turn
                >> omit[+space]
                >> single_move
                >> -(omit[+space] >> single_move)
                >> -(omit[+space] >> lit("1-0") | lit("0-1") | lit("1/2-1/2") | lit("*"))
                ;
 
            game %= +full_move;
        }
 
        //qi::rule<Iterator, pgn_tag(), qi::unused_type> tag;
        //qi::rule<Iterator, std::vector<pgn_tag>, qi::unused_type> header;
        qi::rule<Iterator, std::string(), qi::unused_type> quoted_string;
 
        qi::rule<Iterator, std::string(), qi::unused_type> regular_move;
        qi::rule<Iterator, std::string(), qi::unused_type> castle_move;
        qi::rule<Iterator, std::string(), qi::unused_type> single_move;
        qi::rule<Iterator, std::string(), qi::unused_type> move_turn;
        qi::rule<Iterator, game_move(), qi::unused_type> full_move;
        qi::rule<Iterator, std::vector<game_move>, qi::unused_type> game;
    };
}
 
int main()
{
    using namespace std;
 
    ifstream ifs ("/home/loloof64/Documents/temp/spirit_test_2");
    string input;
    getline(ifs, input, (char) ifs.eof());
 
    loloof64::pgn_parser<string::const_iterator> parser;
    std::vector<loloof64::game_move> game;
 
    string::const_iterator iter = input.begin();
    string::const_iterator end = input.end();
 
    bool success = boost::spirit::qi::phrase_parse(iter, end, parser, boost::spirit::qi::eol, game);
 
    if (success && iter == end)
    {
        for(auto curr_move : game)
        {
            cout << "Number : " << curr_move.move_number << endl;
            cout << "Move turn : " << curr_move.move_turn << endl;
            cout << "white move : " << curr_move.white_move << endl;
            cout << "black move : " << curr_move.black_move << endl;
            cout << "result : " << curr_move.result << endl;
            cout << "------------------------------" << endl;
        }
    }
    else
    {
        cout << "Failed to parse input !" << endl;
        cout << "at " << string(iter, end) << endl;
    }
 
    return 0;
}
Voici le message de compilation :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
||=== Build: Debug in ParsingPgnTest (compiler: GNU GCC Compiler) ===|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp||In constructor ‘loloof64::pgn_parser<Iterator>::pgn_parser()’:|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|82|warning: right shift count >= width of type [-Wshift-count-overflow]|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|82|warning: right shift count >= width of type [-Wshift-count-overflow]|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|82|warning: right shift count >= width of type [-Wshift-count-overflow]|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp||In instantiation of ‘loloof64::pgn_parser<Iterator>::pgn_parser() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >]’:|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|119|required from here|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|82|warning: right shift count >= width of type [-Wshift-count-overflow]|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|82|warning: right shift count >= width of type [-Wshift-count-overflow]|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|82|warning: right shift count >= width of type [-Wshift-count-overflow]|
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp||In instantiation of ‘static void boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::false_) [with Auto = mpl_::bool_<true>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::lexeme>, 0l>&, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::negate, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::char_, boost::spirit::char_encoding::ascii>, boost::fusion::vector1<const char (&)[6]> > >, 0l>&>, 1l>&, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::negate, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::char_, boost::spirit::char_encoding::ascii>, boost::fusion::vector1<const char (&)[7]> > >, 0l>&>, 1l>&>, 2l>&, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const int&>, 0l> >, 2l>&, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::char_, boost::spirit::char_encoding::ascii>, boost::fusion::vector1<const char (&)[4]> > >, 0l>&>, 2l>&, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::char_, boost::spirit::char_encoding::ascii>, boost::fusion::vector1<const char (&)[4]> > >, 0l>&>, 2l>&, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::negate, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const char&>, 0l>, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::char_, boost::spirit::char_encoding::ascii>, boost::fusion::vector1<const char (&)[5]> > >, 0l>&>, 2l>&, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const int&>, 0l> >, 2l>&>, 1l>&>, 2l>&>, 2l>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::__cxx11::basic_string<char>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::false_ = mpl_::bool_<false>]’:|
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp|247|required from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>& boost::spirit::qi::operator%=(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, Expr&&) [with Expr = const boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::lexeme>, 0l>&, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::negate, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::char_, boost::spirit::char_encoding::ascii>, boost::fusion::vector1<const char (&)[6]> > >, 0l>&>, 1l>&, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::negate, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::char_, boost::spirit::char_encoding::ascii>, boost::fusion::vector1<const char (&)[7]> > >, 0l>&>, 1l>&>, 2l>&, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const int&>, 0l> >, 2l>&, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::char_, boost::spirit::char_encoding::ascii>, boost::fusion::vector1<const char (&)[4]> > >, 0l>&>, 2l>&, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::char_, boost::spirit::char_encoding::ascii>, boost::fusion::vector1<const char (&)[4]> > >, 0l>&>, 2l>&, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::negate, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const char&>, 0l>, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::char_, boost::spirit::char_encoding::ascii>, boost::fusion::vector1<const char (&)[5]> > >, 0l>&>, 2l>&, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const int&>, 0l> >, 2l>&>, 1l>&>, 2l>&>, 2l>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::__cxx11::basic_string<char>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|81|required from ‘loloof64::pgn_parser<Iterator>::pgn_parser() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >]’|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|119|required from here|
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp|177|error: static assertion failed: error_invalid_expression|
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp||In instantiation of ‘static void boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::false_) [with Auto = mpl_::bool_<true>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>&, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const int&>, 0l> >, 2l>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::__cxx11::basic_string<char>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::false_ = mpl_::bool_<false>]’:|
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp|247|required from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>& boost::spirit::qi::operator%=(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, Expr&&) [with Expr = const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>&, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const int&>, 0l> >, 2l>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::__cxx11::basic_string<char>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|84|required from ‘loloof64::pgn_parser<Iterator>::pgn_parser() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >]’|
/home/loloof64/Documents/Programmation/ProjetsPersos/Cpp/ParsingPgnTest/main.cpp|119|required from here|
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp|177|error: static assertion failed: error_invalid_expression|
||=== Build failed: 2 error(s), 16 warning(s) (0 minute(s), 21 second(s)) ===|
A mon avis ce sont les regles regular_move et single_move qui posent problème, sans en être sûr.