/* Copyright (c) 1997-2006
Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
http://www.math.tu-berlin.de/polymake, mailto:polymake@math.tu-berlin.de
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version: http://www.gnu.org/licenses/gpl.txt.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef _POLYMAKE_PLAIN_PARSER_H
#define _POLYMAKE_PLAIN_PARSER_H "$Project: polymake $$Id: PlainParser.h 7315 2006-04-02 21:37:53Z gawrilow $"
#include <iostream>
#include <string>
#include <stdexcept>
#ifndef _POLYMAKE_GENERIC_IO_H
# include <GenericIO.h>
#endif
class Rational;
namespace pm {
template <typename Value, typename Options> class PlainListCursor;
template <typename Options> class PlainCompositeCursor;
class PlainParserCommon {
protected:
mutable std::istream *is;
char *saved_egptr;
PlainParserCommon(const PlainParserCommon& other)
: is(other.is), saved_egptr(other.saved_egptr)
{
other.is=0;
}
explicit PlainParserCommon(std::istream& is_arg)
: is(&is_arg), saved_egptr(0) { }
public:
~PlainParserCommon()
{
if (is && saved_egptr) restore_input_range(saved_egptr);
}
template <typename Data>
void fallback(Data& x) { *is >> x; }
void finish() const { }
bool at_end();
void get_scalar(double&);
void get_scalar(Rational&);
void get_string(std::string&, char delim);
int count_lines();
int count_all_lines();
protected:
char* set_temp_range(char opening, char closing);
void set_range(char opening, char closing)
{
saved_egptr=set_temp_range(opening,closing);
}
void discard_range(char closing);
void discard_temp_range(char closing, char *egptr)
{
discard_range(closing);
restore_input_range(egptr);
}
int count_words();
int count_braced(char opening, char closing);
int count_leading(char);
char* set_input_range(int offset);
void restore_input_range(char *egptr);
void skip_temp_range(char *egptr);
char* save_read_pos();
void restore_read_pos(char *pos);
public:
void skip_item();
void skip_rest();
};
template <typename Object, typename Model=typename object_traits<Object>::model>
struct composite_depth {
static const int value=0;
};
template <typename Object>
struct composite_depth<Object, is_composite> {
static const int value= composite_depth<typename n_th<typename object_traits<Object>::elements, 0>::type>::value + 1;
};
template <typename Options=void>
class PlainParser
: public PlainParserCommon,
public GenericInputImpl< PlainParser<Options> >,
public GenericIOoptions< PlainParser<Options>, Options > {
public:
PlainParser(std::istream& is_arg) : PlainParserCommon(is_arg) { }
typedef ostream_wrapper<Options> wrapper;
template <typename ObjectRef>
struct list_cursor {
typedef PlainListCursor<typename deref<ObjectRef>::type::value_type,
typename wrapper::template list_cursor<ObjectRef>::cursor_options>
type;
};
template <typename ObjectRef>
struct composite_cursor {
typedef PlainCompositeCursor<typename wrapper::template composite_cursor<ObjectRef>::cursor_options>
type;
};
template <typename Object>
typename list_cursor<Object>::type begin_list(Object*) const
{
return typename list_cursor<Object>::type(*this->is);
}
template <typename Object>
typename composite_cursor<Object>::type begin_composite(Object*) const
{
return typename composite_cursor<Object>::type(*this->is);
}
operator void* () const { return this->is->good() ? (void*)this : 0; }
bool operator! () const { return !this->is->good(); }
};
template <typename Options> inline
PlainParser<Options>&
operator>> (GenericInput< PlainParser<Options> >& is, double& x)
{
is.top().get_scalar(x);
return is.top();
}
template <typename Options> inline
PlainParser<Options>&
operator>> (GenericInput< PlainParser<Options> >& is, Rational& x)
{
is.top().get_scalar(x);
return is.top();
}
template <typename Options> inline
PlainParser<Options>&
getline (PlainParser<Options>& is, std::string& s, char delim='\n')
{
is.get_string(s,delim);
return is;
}
template <typename Options> inline
PlainParser<Options>&
operator>> (GenericInput< PlainParser<Options> >& is, std::string& s)
{
is.top().get_string(s,0);
return is.top();
}
template <typename Options>
class PlainCursor : public PlainParserCommon {
protected:
char *start_pos;
static const char
opening=extract_int_param<Options, OpeningBracket>::value,
closing=extract_int_param<Options, ClosingBracket>::value,
separator=extract_int_param<Options, SeparatorChar>::value;
static const bool
is_temp=extract_bool_param<Options, LookForward>::value;
public:
PlainCursor(std::istream& is_arg)
: PlainParserCommon(is_arg), start_pos(0)
{
if (is_temp)
start_pos=save_read_pos();
if (opening) set_range(opening, closing);
}
~PlainCursor()
{
if (is_temp)
restore_read_pos(start_pos);
}
void finish()
{
if (closing) discard_range(closing);
}
bool at_end()
{
return PlainParserCommon::at_end() && (finish(), true);
}
PlainParser<Options>* operator-> ()
{
return static_cast<PlainParser<Options>*>(static_cast<PlainParserCommon*>(this));
}
};
template <typename Options>
class PlainCompositeCursor
: public PlainCursor<Options>,
public GenericInputImpl< PlainCompositeCursor<Options> >,
public GenericIOoptions< PlainCompositeCursor<Options>, Options > {
typedef PlainCursor<Options> super;
public:
PlainCompositeCursor(std::istream& is_arg)
: super(is_arg) { }
private:
template <typename Anything>
void cleanup(type2type<Anything>) { }
template <typename Anything, typename Expected>
void cleanup(type2type< ignore<Anything, Expected> >)
{
if (!identical<Expected,nothing>::value) super::skip_item();
}
public:
template <typename Data>
void operator>> (Data& data)
{
*this->operator->() >> data;
cleanup(type2type<Data>());
}
};
template <typename Value, typename Options>
class PlainListCursor
: public PlainCursor<Options>,
public GenericInputImpl< PlainListCursor<Value,Options> >,
public GenericIOoptions< PlainListCursor<Value,Options>, Options, 1 > {
typedef PlainCursor<Options> super;
typedef ostream_wrapper<Options> wrapper;
static const bool has_sparse_representation=extract_bool_param<Options, SparseRepresentation, false>::value;
protected:
int _size;
char *pair_egptr;
int size(is_scalar)
{
return this->count_words();
}
int size(nothing) // e.g. graph incidence line
{
return this->count_words();
}
int size(is_container)
{
typedef typename wrapper::template list_cursor<Value> defs;
return defs::opening
? this->count_braced(defs::opening, defs::closing) :
super::opening
? this->count_lines()
: this->count_all_lines();
}
int size(is_composite)
{
typedef typename wrapper::template composite_cursor<Value> defs;
return defs::opening
? this->count_braced(defs::opening, defs::closing) :
super::separator=='\n'
? super::opening
? this->count_lines()
: this->count_all_lines()
: this->count_words();
}
public:
typedef Value value_type;
PlainListCursor(std::istream& is_arg)
: super(is_arg), _size(-1), pair_egptr(0)
{
if (!super::opening && object_traits<Value>::total_dimension==0)
this->set_range(0, '\n');
}
int size()
{
if (_size<0)
_size=size(typename object_traits<Value>::model());
return _size;
}
protected:
template <typename Model>
static int missing_parens(Model) { return 0; }
static int missing_parens(is_composite)
{
typedef typename wrapper::template composite_cursor<Value> defs;
return defs::opening == 0;
}
bool _sparse_representation()
{
const int own_missing=missing_parens(typename object_traits<Value>::model());
return this->count_leading('(') == composite_depth<Value>::value - own_missing + 1;
}
public:
int index()
{
if (!ignore_in_composite<Value>::value) {
if (has_sparse_representation)
pair_egptr=this->set_temp_range('(', ')');
else
this->is->setstate(std::ios::failbit);
}
int i;
*this->is >> i;
return i;
}
int get_dim()
{
int d=index();
this->discard_temp_range(')', pair_egptr);
pair_egptr=0;
return d;
}
bool sparse_representation()
{
return extract_type_param<Options,SparseRepresentation>::specified
? has_sparse_representation
: _sparse_representation();
}
int dim()
{
return !ignore_in_composite<Value>::value && sparse_representation()
? this->set_option(SparseRepresentation<True>()).get_dim()
: size();
}
private:
template <typename Anything>
void cleanup(type2type<Anything>)
{
if (has_sparse_representation) {
this->discard_temp_range(')', pair_egptr);
pair_egptr=0;
}
}
void cleanup(type2type<nothing>) { }
template <typename Anything, typename Expected>
void cleanup(type2type< ignore<Anything, Expected> >)
{
if (!identical<Expected,nothing>::value) skip_item();
}
public:
template <typename Data>
void operator>> (Data& x)
{
*this->operator->() >> x;
cleanup(type2type<Value>());
}
void skip_item()
{
if (has_sparse_representation && pair_egptr) {
this->skip_temp_range(pair_egptr);
pair_egptr=0;
} else {
super::skip_item();
}
}
};
} // end namespace pm
#endif // _POLYMAKE_PLAIN_PARSER_H
// Local Variables:
// mode:C++
// End:
syntax highlighted by Code2HTML, v. 0.9.1