Quel est le problème avec ce simple boost :: esprit :: Parser qi?
-
01-10-2019 - |
Question
J'ai cet analyseur simple, destiné à Parse style VB cordes doubles guillemets. Ainsi, l'analyseur doit tourner quelque chose comme
"This is a quoted string containing quotes ("" "")"
en un signal de sortie
This is a quoted string containing quotes (" ")
Voici la grammaire que je suis venu avec pour cela:
namespace qi = boost::spirit::qi;
namespace wide = qi::standard_wide;
class ConfigurationParser : public qi::grammar<std::wstring::iterator, std::wstring()>
{
qi::rule<std::wstring::iterator, std::wstring()> quotedString;
qi::rule<std::wstring::iterator> doubleQuote;
public:
ConfigurationParser() : ConfigurationParser::base_type(quotedString, "vFind Command Line")
{
doubleQuote = (wide::char_(L'"') >> wide::char_(L'"'));
quotedString = L'"' >> +(doubleQuote[qi::_val = L'"'] | (wide::char_ - L'"'))>> L'"';
}
};
Cependant, l'attribut que je reçois est une marque de guillemet simple ( "), plutôt que le message complet analysable.
La solution
Vous pouvez le faire sans aucune action sémantique:
class ConfigurationParser
: public qi::grammar<std::wstring::iterator, std::wstring()>
{
qi::rule<std::wstring::iterator, std::wstring()> quotedString;
qi::rule<std::wstring::iterator, wchar_t()> doubleQuote;
public:
ConfigurationParser()
: ConfigurationParser::base_type(quotedString, "vFind Command Line")
{
doubleQuote = wide::char_(L'"') >> omit[wide::char_(L'"')];
quotedString = L'"' >> +(doubleQuote | (wide::char_ - L'"')) >> L'"';
}
};
La directive omit[]
exécute toujours l'analyseur intégré, mais ne met pas en attribut, ce qui rend la règle doublequote retourner une seule L'"'
.
Autres conseils
Je pense que vous ne sauvegardez le résultat correctement:
doubleQuote[qi::_val = L'"']
Ici, en raison de la « = » signe, vous substituez ce qui était déjà. Essayez avec « + = » à la place.
doubleQuote[qi::_val += L'"']
En outre, je ne sais pas si l'épargne est automatique, vous devrez peut-être ajouter le même « + = » après l'autre analyseur à titre subsidiaire:
(wide::char_ - L'"')[qi::_val += boost::spirit::arg_names::_1]
Mais je ne suis pas bon avec Qi donc peut-être il est automatisé, ce qui serait logique.
Eh bien, je ne suis pas vraiment pourquoi, mais j'ai pu corriger en proposant que l'action d'affectation dans la règle sous:
doubleQuote %= (wide::char_(L'"') >> L'"')[qi::_val = L'"'];
doubleQuote.name("double quote");
quotedString = L'"' >> +(doubleQuote | (wide::char_ - L'"')) >> L'"';
quotedString.name("quoted string");
Notez l'utilisation de operator %=
pour guillemet et le fait que l'action sémantique se trouve maintenant là.