Bonjour,

Je me trouve face à un problème très simple (à expliquer), j'ai fait un petit programme compilable :

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
 
#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_core.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
 
#include <iostream>
#include <fstream>
#include <string>
 
using namespace boost::spirit;
using boost::phoenix::val;
 
// Token definition base, defines all tokens for the base grammar below
template <typename Lexer>
struct sql_tokens : lex::lexer<Lexer>
{
public:
    // Tokens with no attributes.
    lex::token_def<lex::omit> kw_unique;
 
    sql_tokens()
    {
        kw_unique = "unique";
 
        // The token must be added in priority order.
        this->self += kw_unique;
    }
};
 
// Grammar definition, define a little part of the SQL language.
template <typename Iterator, typename Lexer>
struct sql_grammar 
  : qi::grammar<Iterator, qi::in_state_skipper<Lexer> >
{
    template <typename TokenDef>
    sql_grammar(TokenDef const& tok)
      : sql_grammar::base_type(program, "program")
    {
        program = keywords.alias();
        keywords = tok.kw_unique;
    }
 
    typedef qi::in_state_skipper<Lexer> skipper_type;
 
    qi::rule<Iterator, skipper_type> program, keywords;
};
 
int main(int argc, char* argv[])
{
    if(argc != 2)
        exit(1);
    // iterator type used to expose the underlying input stream
    typedef std::string::iterator base_iterator_type;
    typedef lex::lexertl::token<base_iterator_type> token_type;
 
    // Here we use the lexertl based lexer engine.
    typedef lex::lexertl::lexer<token_type> lexer_type;
 
    // This is the token definition type (derived from the given lexer type).
    typedef sql_tokens<lexer_type> sql_tokens;
 
    // this is the iterator type exposed by the lexer 
    typedef sql_tokens::iterator_type iterator_type;
 
    // this is the type of the grammar to parse
    typedef sql_grammar<iterator_type, sql_tokens::lexer_def> sql_grammar;
 
    // now we use the types defined above to create the lexer and grammar
    // object instances needed to invoke the parsing process
    sql_tokens tokens;                         // Our lexer
    sql_grammar sql(tokens);                  // Our parser
 
    std::string str(argv[1]);
 
    // At this point we generate the iterator pair used to expose the
    // tokenized input stream.
    std::string::iterator it = str.begin();
    iterator_type iter = tokens.begin(it, str.end());
    iterator_type end = tokens.end();
 
    // Parsing is done based on the the token stream, not the character 
    // stream read from the input.
    // Note how we use the lexer defined above as the skip parser. It must
    // be explicitly wrapped inside a state directive, switching the lexer 
    // state for the duration of skipping whitespace.
    std::string ws("WS");
    bool r = qi::phrase_parse(iter, end, sql, qi::in_state(ws)[tokens.self]);
 
 
    if (r && iter == end)
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing succeeded\n";
        std::cout << "-------------------------\n";
    }
    else
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing failed\n";
        std::cout << "-------------------------\n";
    }
    return 0;
}
J'ai testé ces différentes possibilités pour ignorer la case :

Encapsuler toute la grammaire dans le "no_case".
Code : Sélectionner tout - Visualiser dans une fenêtre à part
bool r = qi::phrase_parse(iter, end, qi::ascii::no_case[sql], qi::in_state(ws)[tokens.self]);
Seulement quelques règles :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
program = qi::ascii::no_case[keywords];
        keywords = tok.kw_unique;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
program = keywords.alias();
        keywords = qi::ascii::no_case[tok.kw_unique];
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
program = qi::ascii::no_case[keywords];
        keywords = qi::ascii::no_case[tok.kw_unique];
Rien ne marche, j'ai même essayé de modifié les expressions régulières avec "(?i)" pour activer la non-sensibilité à la case mais cette option n'est pas supportée.

Et j'ai pas très envie de faire :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
kw_unique = "(unique|UNIQUE)";
Ou encore plus énervant :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
kw_unique = "([uU][nN][iI]...";
Vous pouvez tester le programme en le lançant comme ça :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
.\sql_parser unique
.\sql_parser UNIQUE
Merci pour l'aide !