Por mi propio marco pequeño analizador, estoy tratando de definir (algo así como) la siguiente función:"copia de carbono" a C++ istream?
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. */
}
entonces podría escribir algo como esto: (quizás no es el mejor ejemplo)
/* 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;
}
Cualquier ayuda es muy apreciada.
Las transmisiones no son la herramienta adecuada para esto, debido a su falta de recuperación adecuada. Al diseñar analizadores simples en línea como este (de lo contrario, intente 'boost :: spirit'), las funciones de análisis realmente deberían tener un par de iteradores. Es fácil retrotraer (solo guarde el valor del iterador antes de un analizador de retroceso). –