Pour ma propre cadre peu d'analyse syntaxique, je suis en train de définir (quelque chose comme) la fonction suivante:"copie carbone" un istream C++?
template <class T>
// with operator>>(std::istream&, T&)
void tryParse(std::istream& is, T& tgt)
{
is >> tgt /* , *BUT* store every character that is consumed by this operation
in some string. If afterwards, is.fail() (which should indicate a parsing
error for now), put all the characters read back into the 'is' stream so that
we can try a different parser. */
}
alors je pourrais écrire quelque chose comme ceci: (peut-être pas le meilleur exemple)
/* grammar: MyData = <IntTriple> | <DoublePair>
DoublePair = <double> <double>
IntTriple = <int> <int> <int> */
class MyData
{ public:
union { DoublePair dp; IntTriple it; } data;
bool isDoublePair;
};
istream& operator>>(istream& is, MyData& md)
{
/* If I used just "is >> md.data.it" here instead, the
operator>>(..., IntTriple) might consume two ints, then hit an
unexpected character, and fail, making it impossible to read these two
numbers as doubles in the "else" branch below. */
tryParse(is, md.data.it);
if (!is.fail())
md.isDoublePair = false;
else
{
md.isDoublePair = true;
is.clear();
is >> md.data.dp;
}
return is;
}
Toute aide est grandement appréciée.
Les flux ne sont pas l'outil idéal pour cela, en raison de leur manque de recul approprié. Lors de la conception de simples analyseurs en ligne de ce type (sinon, essayez d'utiliser boost :: spirit), les fonctions d'analyse devraient utiliser une paire d'itérateurs. Il devient facile de revenir en arrière (il suffit de sauvegarder la valeur de l'itérateur avant un analyseur de retour arrière). –