I've got to write a BASIC to C++ converter and came across the problem of
the DATA statement.
I must provide a way of storing:
DATA 5.123, "abc", ...
in C++. [..]
but &123.4 is not possible. Now, having temporary global variables for this
doesn't make me too happy either.
Is there a "clean" way of doing this?
Try this approach:
#include <list>
#include <string>
#include <stdexcpt>
class Data {
public:
typedef enum { String, Double } Type;
Data( const std::string& s ) : str( s ), dbl( 0 ), type( String )
{}
Data( const double d ) : str( "" ), dbl( d ), type( Double ) {}
class Exception : public std::exception {
public:
Exception( const std::string& s ) : std::exception( s.c_str() )
{}
};
Type GetType() const { return type; }
const std::string& GetSValue() const {
if ( GetType() == String ) return str;
else throw Exception( "DATA type is String" );
}
double GetDValue() const {
if ( GetType() == Double ) return dbl;
else throw Exception( "DATA type is Double" );
}
private:
std::string str;
double dbl;
Type type;
};
class Repository : private std::list<Data> {
public:
Repository( const Data* beg, const Data* end )
: std::list<Data>( beg, end ), current( begin() )
{}
const Data& Read() {
if ( current == end() ) Restore(); // or throw exception
return *(current++);
}
void Restore() { current = begin(); }
void Restore( const int lineno ) {
// left as an exercise
you need another private
// container member, e.g.
// std::map<unsigned int, std::list<Data>::const_iterator>
// recording the line numbers and the start of the corresponding
// DATA content.
}
private:
std::list<Data>::const_iterator current;
};
.....
DATA 123.4, "xy" translates to:
static Data data[] = { Data( 123.4 ), Data( "xy" ) /* , ... */ };
Repository MyData( &data[0], &data[sizeof(data) / sizeof(Data)] );
You may want to collect all DATA statements in your translator before
you write out the generated code.
Each READ X translates to:
double X;
/* ... */
X = MyData.Read().GetDValue();
Each READ Y$ translates to:
std::string Y;
/* ... */
Y = MyData.Read().GetSValue();
Violation of data types result in an exception - just like BASIC gives
an error.
Each RESTORE translates to:
MyData.Restore();
best,
Michael