/*---------------------------------------------------------------------------*
* IT++ *
*---------------------------------------------------------------------------*
* Copyright (c) 1995-2003 by Tony Ottosson, Thomas Eriksson, Pål Frenger, *
* Tobias Ringström, and Jonas Samuelsson. *
* *
* Permission to use, copy, modify, and distribute this software and its *
* documentation under the terms of the GNU General Public License is hereby *
* granted. No representations are made about the suitability of this *
* software for any purpose. It is provided "as is" without expressed or *
* implied warranty. See the GNU General Public License for more details. *
*---------------------------------------------------------------------------*/
/*!
\file
\brief Implementation of an argument parser class.
\author Thomas Eriksson and Pål Frenger (Thanks to Svante Signell for valuable input)
1.20
2004/10/06 00:18:12
*/
#include "base/parser.h"
#include "base/vec.h"
#include "base/mat.h"
#include <iostream>
#include <fstream>
#include <string>
using std::cout;
using std::string;
using std::endl;
namespace itpp {
Parser::Parser()
{
VERBOSE=true;
}
Parser::Parser(const string &filename)
{
VERBOSE=true;
init(filename);
}
Parser::Parser(int argc, char *argv[])
{
VERBOSE=true;
init(argc,argv);
}
Parser::Parser(const string &filename, int argc, char *argv[])
{
VERBOSE=true;
init(filename, argc, argv);
}
Parser::Parser(const Array<string> &setup)
{
VERBOSE=true;
init(setup);
}
void Parser::pre_parsing(void)
{
int i, j, n, k;
int count = 0;
int size = SetupStrings.size();
bool cont_line;
string Line, NewLine;
Array<string> TempSetupStrings;
// Remove lines starting with '%' or have zero length:
for (i=0; i<size; i++) {
Line = SetupStrings(i);
if ((Line[0]!='%') && (Line.length() != 0)) {
SetupStrings(count) = Line;
count++;
}
}
SetupStrings.set_size(count,true);
size = SetupStrings.size();
//Check for '...' continuation as in Matlab:
count = 0;
NewLine = "";
for (i=0; i<SetupStrings.size(); i++) {
Line = SetupStrings(i);
n = Line.size();
cont_line = false;
for (k=0; k<(n-2); k++) {
if ((Line[k]=='.') && (Line[k+1]=='.') && (Line[k+2]=='.')) {
cont_line = true; break;
}
}
if (cont_line) {
for (j=0; j<k; j++) { NewLine += Line[j]; }
} else {
NewLine += Line;
SetupStrings(count) = NewLine;
count++;
NewLine = "";
}
}
SetupStrings.set_size(count,true);
//Strip unneccesary blanks, tabs, and newlines:
size = SetupStrings.size();
for (i=0; i<size; i++) {
NewLine = "";
Line = SetupStrings(i);
n = Line.length();
j = 0; //counter in Line
while (j<n) {
switch (Line[j]) {
case '\n':
//Remove newlines
j++;
break;
case ' ':
//Remove blanks
j++;
break;
case '\t':
//Remove tabs
j++;
break;
case '[':
//Don't remove blanks between '[' and ']'
while ( (Line[j] != ']') && ( j < n ) ) { NewLine += Line[j]; j++; }
if (j<n) { NewLine += Line[j]; j++; }
break;
case '{':
//Don't remove blanks between '{' and '}'
while ( (Line[j] != '}') && ( j < n ) ) { NewLine += Line[j]; j++; }
if (j<n) { NewLine += Line[j]; j++; }
break;
case '"':
//Don't remove blanks between '"' and '"'
NewLine += Line[j]; j++; //Read in the first '"'
while ( (Line[j] != '"') && ( j < n ) ) { NewLine += Line[j]; j++; }
NewLine += Line[j]; j++;
break;
case '\'':
//Don't remove blanks between '\'' and '\''
NewLine += Line[j]; j++; //Read in the first '\''
while ( (Line[j] != '\'') && ( j < n ) ) { NewLine += Line[j]; j++; }
NewLine += Line[j]; j++;
break;
case '%':
//Remove trailing comments
j = n;
break;
default:
//Keep the current character:
NewLine += Line[j]; j++;
break;
}
}
SetupStrings(i) = NewLine;
}
// Split lines with several expressions (i.e. a=3;b=[1 2 3],c="Hello World") on the same line
// (separated by comma or semicolon)
TempSetupStrings.set_size(size,false);
count = 0; //Counter in TempSetupStrings
for (i=0; i<size; i++) {
NewLine = "";
Line = SetupStrings(i);
n = Line.length();
j = 0;
while (j<n) {
switch (Line[j]) {
case '[':
//A vector or a matrix
while ( (Line[j] != ']') && ( j < n ) ) { NewLine += Line[j]; j++; }
if (Line[j]==']') { NewLine += Line[j]; j++; }
if (j==n) {
if (count>=TempSetupStrings.size()) { TempSetupStrings.set_size(2*count,true); }
TempSetupStrings(count) = NewLine; NewLine = ""; count++;
}
break;
case '"':
//A string
NewLine += Line[j]; j++; //Read in the first '"'
while ( (Line[j] != '"') && ( j < n ) ) { NewLine += Line[j]; j++; }
if (Line[j]=='"') { NewLine += Line[j]; j++; }
if (j==n) {
if (count>=TempSetupStrings.size()) { TempSetupStrings.set_size(2*count,true); }
TempSetupStrings(count) = NewLine; NewLine = ""; count++;
}
break;
case '\'':
//A string
NewLine += Line[j]; j++; //Read in the first '\''
while ( (Line[j] != '\'') && ( j < n ) ) { NewLine += Line[j]; j++; }
if (Line[j]=='\'') { NewLine += Line[j]; j++; }
if (j==n) {
if (count>=TempSetupStrings.size()) { TempSetupStrings.set_size(2*count,true); }
TempSetupStrings(count) = NewLine; NewLine = ""; count++;
}
break;
case ',':
//Expression ends here
if (count>=TempSetupStrings.size()) { TempSetupStrings.set_size(2*count,true); }
TempSetupStrings(count) = NewLine;
NewLine = ""; count++; j++;
break;
case ';':
//Expression ends here
if (count>=TempSetupStrings.size()) { TempSetupStrings.set_size(2*count,true); }
TempSetupStrings(count) = NewLine + ';';
NewLine = ""; count++; j++;
break;
default:
//Copy the current character:
NewLine += Line[j];
j++;
if (j==n) {
if (count>=TempSetupStrings.size()) { TempSetupStrings.set_size(2*count,true); }
TempSetupStrings(count) = NewLine; NewLine = ""; count++;
}
break;
}
}
}
TempSetupStrings.set_size(count,true);
SetupStrings = TempSetupStrings;
}
void Parser::init(const string &filename)
{
string Line;
SetupStrings.set_size(0,false);
std::ifstream SetupFile(filename.c_str());
while (getline(SetupFile,Line,'\n')) {
SetupStrings.set_size( SetupStrings.size() + 1, true );
SetupStrings( SetupStrings.size() - 1 ) = Line;
}
SetupFile.close();
pre_parsing();
}
void Parser::init(int argc, char *argv[])
{
SetupStrings.set_size(argc);
int i;
for (i=0; i<argc; i++) {
SetupStrings(i) = argv[i];
}
pre_parsing();
}
void Parser::init(const string &filename, int argc, char *argv[])
{
string Line;
int i;
std::ifstream SetupFile(filename.c_str());
//Read the command line parameters:
SetupStrings.set_size(argc);
for (i=0; i<argc; i++) {
SetupStrings(i) = argv[i];
}
//Read the file parameters:
while (getline(SetupFile,Line,'\n')) {
SetupStrings.set_size( SetupStrings.size() + 1, true );
SetupStrings( SetupStrings.size() - 1 ) = Line;
}
SetupFile.close();
pre_parsing();
}
void Parser::init(const Array<string> &setup)
{
SetupStrings = setup;
pre_parsing();
}
void Parser::set_silentmode(bool v)
{
VERBOSE=!v;
}
bool Parser::exist(const std::string &name)
{
bool error_flag, print_flag;
string temp = findname( name, error_flag, print_flag );
if (error_flag) {
return false;
} else {
return true;
}
}
template<>
bool Parser::get(std::string &var, const std::string &name, int num)
{
bool error_flag, print_flag;
string str = findname(name, error_flag, print_flag, num);
if (error_flag) {
if (VERBOSE) {
cout << name << " = '" << var << "';" << endl;
}
} else {
var = str;
if (print_flag) {
cout << name << " = '" << var << "'" << endl;
} else if (VERBOSE) {
cout << name << " = '" << var << "';" << endl;
}
}
return !error_flag;
}
bool Parser::get_bool(const string &name, int num)
{
bool out;
bool error_flag, print_flag;
out = atof(findname(name,error_flag,print_flag,num).c_str())==1;
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing bool : " << name << " = " << out << endl; }
return out;
}
int Parser::get_int(const string &name, int num)
{
int out;
bool error_flag, print_flag;
out = int(atof(findname(name,error_flag,print_flag,num).c_str()));
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing int : " << name << " = " << out << endl; }
return out;
}
double Parser::get_double(const string &name, int num)
{
double out;
bool error_flag, print_flag;
out = atof(findname(name,error_flag,print_flag,num).c_str());
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing double: " << name << " = " << out << endl; }
return out;
}
string Parser::get_string(const string &name, int num)
{
string out;
bool error_flag, print_flag;
out = findname(name,error_flag,print_flag,num);
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing string: " << name << " = " << out << endl; }
return out;
}
vec Parser::get_vec(const string &name, int num)
{
vec out;
bool error_flag, print_flag;
out = vec(findname(name,error_flag,print_flag,num));
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing vec : " << name << " = " << out << endl; }
return out;
}
ivec Parser::get_ivec(const string &name, int num)
{
ivec out;
bool error_flag, print_flag;
out = ivec(findname(name,error_flag,print_flag,num));
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing ivec : " << name << " = " << out << endl; }
return out;
}
svec Parser::get_svec(const string &name, int num)
{
svec out;
bool error_flag, print_flag;
out = svec(findname(name,error_flag,print_flag,num));
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing svec : " << name << " = " << out << endl; }
return out;
}
bvec Parser::get_bvec(const string &name, int num)
{
bvec out;
bool error_flag, print_flag;
out = bvec(findname(name,error_flag,print_flag,num));
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing bvec : " << name << " = " << out << endl; }
return out;
}
mat Parser::get_mat(const string &name, int num)
{
mat out;
bool error_flag, print_flag;
out = mat(findname(name,error_flag,print_flag,num));
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing mat : " << name << " = " << out << endl; }
return out;
}
imat Parser::get_imat(const string &name, int num)
{
imat out;
bool error_flag, print_flag;
out = imat(findname(name,error_flag,print_flag,num));
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing imat : " << name << " = " << out << endl; }
return out;
}
smat Parser::get_smat(const string &name, int num)
{
smat out;
bool error_flag, print_flag;
out = smat(findname(name,error_flag,print_flag,num));
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing smat : " << name << " = " << out << endl; }
return out;
}
bmat Parser::get_bmat(const string &name, int num)
{
bmat out;
bool error_flag, print_flag;
out = bmat(findname(name,error_flag,print_flag,num));
if (error_flag) { it_error("Parser: Can not find variable: " + name); }
if (print_flag) { cout << "Parsing bmat : " << name << " = " << out << endl; }
return out;
}
string Parser::findname(const string &name, bool &error_flag, bool &print_flag, int num, bool keep_brackets)
{
string Name, Out, Line, Temp;
int n, j=0, i=0, index=-1;
bool found = false, vec_mat = false;
error_flag = false;
print_flag = false;
if (num<0) { num=0; }
Name = "";
// Go through all words in input string to find a match
while (i < SetupStrings.size()) {
Line = SetupStrings(i); i++;
// Find equal sign "=", and take the left part to be the Name
if (Line.find_first_of("=") != string::npos) {
Name = Line.substr(0, Line.find_first_of("="));
} else {
Name = "";
}
if (Name==name) {
if (found) {
//cout << "Parser Warning: Duplicate Entry of variable " << name << endl;
} else {
found = true;
index = i-1;
}
}
}
// if we have a match
if ( (found) && (index+num <= SetupStrings.size()) ) {
Line = SetupStrings(index+num);
if (num != 0) {
Temp = Line;
} else {
Temp = Line.substr(Line.find_first_of("=")+1);
}
} else {
error_flag = true;
return "";
}
//Remove [, ],",' and ending ;. Set the print_flag:
n = Temp.size();
Out = "";
for (i=0; i<n; i++) {
switch (Temp[i]) {
case '[':
vec_mat = true;
if (keep_brackets) { Out += Temp[i]; }
if (i==(n-1)) { print_flag = true; }
break;
case ']':
if (keep_brackets) { Out += Temp[i]; }
if (i==(n-1)) { print_flag = true; }
break;
case '"':
if (i==(n-1)) { print_flag = true; }
break;
case '\'':
if (i==(n-1)) { print_flag = true; }
break;
case ';':
if (i==(n-1)) { print_flag = false; } else { Out += Temp[i]; }
break;
default:
Out += Temp[i];
if (i==(n-1)) { print_flag = true; }
break;
}
}
//Final parsing of vectors and matrices:
if (vec_mat) {
Temp = Out;
Out = "";
n = Temp.size();
j = 0;
while ((Temp[j] == ' ') || (Temp[j] == '\t') || (Temp[j] == '\n')) { j++; } //Remove spaces/tabs/newline in beginning
while ((Temp[n-1] == ' ') || (Temp[n-1] == '\t') || (Temp[n-1] == '\n')) { n--; } //Remove spaces/tabs/newline at the end
while (j<n) {
//Read in data element:
while ((Temp[j]!=' ')&&(Temp[j]!='\t')&&(Temp[j]!='\n')&&(Temp[j]!=',')&&(Temp[j]!=';')&&(j<n)) {
Out += Temp[j]; j++;
}
//Read separator:
if (j<(n-1)) {
//Remove spaces before separator
while (((Temp[j]==' ')||(Temp[j]=='\t')||(Temp[j]=='\n'))&&(j<n)) { j++; }
//Insert Separator:
if (j<n) {
if (Temp[j]==';') { Out += ';'; j++; }
else if (Temp[j]==',') { Out += Temp[j]; j++; }
else if (Temp[j]=='+') { Out += ','; Out += Temp[j]; j++; }
else if (Temp[j]=='-') { Out += ','; Out += Temp[j]; j++; }
else { Out += ','; }
}
//Remove spaces after separator:
while (((Temp[j]==' ')||(Temp[j]=='\t')||(Temp[j]=='\n'))&&(j<n)) { j++; }
}
}
}
if (!VERBOSE) print_flag=false;
return Out;
}
} //namespace itpp
syntax highlighted by Code2HTML, v. 0.9.1