Bonjour,

J'essaye de réaliser un parser de multiple affectation. Un exemple vaut mieux que mille mots :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
// affectation "normal"
key1 = value1
key2 = value2
 
// multiple affectation
key1, key2 = value1, value2
Sachant qu'on les contraintes suivantes :

If there are extra keys, they will be set to an empty value. If there are extra values the last key will be set to the comma-separated list of all remaining values.
Vu qu'un parser est récursif j'ai vraiment des difficultés à parser et stocker cette écriture.

Je dois pouvoir la stocker dans

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
struct attribute
{
  std::string key;
  std::string value;
};
 
typedef std::vector<attribute> all_attribute;
J'ai retourner le problème dans tout les sens pour arriver à la stocker la dedans mais je ne suis pas arriver.

Première Question : Comment faire avec Boost.Spirit (ou alors n'hésitez à mettre une pseudo-grammaire en EBNF) ?

Par conséquent, j'ai créé une structure spécifique pour les multi assignement attribute comme ceci :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
struct multi_attribute
{
  std::vector<std::string> keys;
  std::vector<std::string> values;
};
Comme ça je rempli l'un puis l'autre... Voici mon parser :

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
using qi::lit;
using qi::lexeme;
using qi::eol;
using qi::eoi;
using ascii::char_;
using ascii::string;
using ascii::space;
using namespace qi::labels;
 
using phoenix::at_c;
using phoenix::push_back;
using phoenix::if_;
using phoenix::back;
using phoenix::size;
 
string_rule = *lit('"') >> lexeme[+(char_("a-zA-Z0-9") | char_('.'))[_val += _1]] >> *lit('"');
 
key %= string_rule;
value %= string_rule;
 
multiattribute =
     key[push_back(at_c<0>(_val), _1)] % ','
  >> '='
  >> value[if_(size(at_c<0>(_val)) > size(at_c<1>(_val)))
            [
              push_back(at_c<1>(_val), _1)
            ]
            .else_
            [
              back(at_c<1>(_val)) += ',' + _1
            ]
          ]
     % ','
  >> *eol
;
Ne vous étonnez pas des règles key et value qui ne servent à rien pour le moment, elles me serviront plus tard

Et voici mon test case :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
[multiattributetests]
  key1, key2 = 1, no  // OK
  key1, key2, key3 = 1, value1  // OK
  key1,         key2 = value1    ,   value2  , value3  // OK
  key1 = value1  // OK
  key1 = 1, 2 , 3  // KO
[/multiattributetests]
En effet, lorsqu'il n'y a qu'une left value et plusieurs right values j'ai une erreur de parsing...

Je ne comprend absolument pas pourquoi.

Deuxième question
: Pourquoi ?

Merci d'avance.