1332 lines
28 KiB
C++

// Parser.cpp: implementation of the CParser class.
//
//////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
#pragma warning(disable : 4786) // disable truncation warning (Only used by debugger)
#endif
#include <algorithm> // std::transform
#include <map> // std::map
#include <cassert> // assert
#include <stdlib.h>
#include <iostream> // std::cout std::cerr
#include "Utils.h"
#include <stdio.h>
#include "Parser.h"
#include "PHRQ_io.h"
#if defined(PHREEQCI_GUI)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CParser::CParser(PHRQ_io *io):
PHRQ_base(io),
m_input_stream(std::cin),
m_input_error(0),
m_next_keyword(Keywords::KEY_NONE)
{
if (!io)
{
error_msg("This parser constructor requires non-null phrq_io", PHRQ_io::OT_STOP);
echo_file = EO_ALL;
echo_stream = EO_NONE;
accumulate = false;
phrq_io_only = true;
m_line_type = PHRQ_io::LT_EMPTY;
}
else
{
m_line_save = io->Get_m_line();
m_line = io->Get_m_line();
m_line_type = io->Get_m_line_type();
m_line_iss.str(m_line);
m_line_iss.seekg(0, std::ios_base::beg);
m_line_iss.clear();
echo_file = EO_ALL;
echo_stream = EO_NONE;
accumulate = false;
phrq_io_only = true;
}
}
CParser::CParser(std::istream & input, PHRQ_io *io):
PHRQ_base(io),
m_input_stream(input),
m_input_error(0),
m_next_keyword(Keywords::KEY_NONE)
{
m_line_save.reserve(80);
m_line.reserve(80);
echo_file = EO_ALL;
echo_stream = EO_NONE;
accumulate = false;
phrq_io_only = false;
m_line_type = PHRQ_io::LT_EMPTY;
}
CParser::~CParser()
{
}
PHRQ_io::LINE_TYPE CParser::check_line(const std::string & str,
bool allow_empty, bool allow_eof,
bool allow_keyword, bool print)
{
PHRQ_io::LINE_TYPE
i;
// Get line
do
{
i = get_line();
// reset iss
m_line_iss.str(m_line);
m_line_iss.seekg(0, std::ios_base::beg);
m_line_iss.clear();
// output for stream
switch (this->echo_stream)
{
case EO_NONE:
break;
case EO_ALL:
if (i != PHRQ_io::LT_EOF)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
//get_output() << msg;
io->output_msg(msg.str().c_str());
}
break;
case EO_KEYWORDS:
if (i == PHRQ_io::LT_KEYWORD)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
//get_output() << msg;
io->output_msg(msg.str().c_str());
}
break;
case EO_NOKEYWORDS:
if (i != PHRQ_io::LT_KEYWORD && i != PHRQ_io::LT_EOF)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
//get_output() << msg;
io->output_msg(msg.str().c_str());
}
break;
}
// output for file
switch (this->echo_file)
{
case EO_NONE:
break;
case EO_ALL:
if (i != PHRQ_io::LT_EOF)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
this->echo_msg(msg.str());
}
break;
case EO_KEYWORDS:
if (i == PHRQ_io::LT_KEYWORD)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
this->echo_msg(msg.str());
}
break;
case EO_NOKEYWORDS:
if (i != PHRQ_io::LT_KEYWORD && i != PHRQ_io::LT_EOF)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
this->echo_msg(msg.str().c_str());
}
break;
}
}
while (i == PHRQ_io::LT_EMPTY && allow_empty == false);
// Check eof
if (i == PHRQ_io::LT_EOF && allow_eof == false)
{
std::ostringstream msg;
msg << "Unexpected eof while reading " << str <<
"\nExecution terminated.\n";
error_msg(msg.str().c_str(), PHRQ_io::OT_STOP);
}
// Check keyword
if (i == PHRQ_io::LT_KEYWORD && allow_keyword == false)
{
std::ostringstream msg;
msg << "Expected data for " << str <<
", but got a keyword ending data block.";
error_msg(msg.str().c_str(), PHRQ_io::OT_CONTINUE);
incr_input_error();
}
m_line_type = i;
return i;
}
PHRQ_io::LINE_TYPE CParser::get_line_phrq_io()
{
m_line_type = io->get_line();
m_line_save = io->Get_m_line_save();
m_line = io->Get_m_line();
m_next_keyword = io->Get_m_next_keyword();
if (accumulate)
{
this->accumulated.append(m_line_save);
this->accumulated.append("\n");
}
return m_line_type;
}
PHRQ_io::LINE_TYPE CParser::get_line()
{
if (this->phrq_io_only)
{
return get_line_phrq_io();
}
PHRQ_io::LINE_TYPE return_value = PHRQ_io::LT_EMPTY;
while (return_value == PHRQ_io::LT_EMPTY)
{
//
// Eliminate all characters after # sign as a comment
//
//
// Get line, check for eof
//
if (get_logical_line() == PHRQ_io::LT_EOF)
{
if (!m_input_stream.eof())
{
error_msg("Reading input file.", PHRQ_io::OT_CONTINUE);
error_msg("istream::get() returned an error.", PHRQ_io::OT_STOP);
}
else
{
//{{MOD
m_line.erase(m_line.begin(), m_line.end()); // m_line.clear();
//}}MOD
m_next_keyword = Keywords::KEY_END;
return PHRQ_io::LT_EOF;
}
}
//
// Get long lines
//
bool
empty = true;
m_line = m_line_save.substr(0, m_line_save.find_first_of('#'));
for (unsigned int i = 0; i < m_line.size(); ++i)
{
if (!::isspace(m_line[i]))
{
empty = false;
break;
}
}
if (this->accumulate)
{
this->accumulated.append(m_line_save);
this->accumulated.append("\n");
}
//
// New line character encountered
//
return_value = (empty ? PHRQ_io::LT_EMPTY : PHRQ_io::LT_OK);
}
//
// Determine return_value
//
if (return_value == PHRQ_io::LT_OK)
{
if (check_key(m_line.begin(), m_line.end()))
{
return_value = PHRQ_io::LT_KEYWORD;
}
else
{
std::string::iterator beg = m_line.begin();
std::string::iterator end = m_line.end();
std::string token;
copy_token(token, beg, end);
if (token.size() > 1 && token[0] == '-' &&::isalpha(token[1]))
{
return_value = PHRQ_io::LT_OPTION;
}
}
}
return return_value;
}
/**
Reads input stream until end of line, ";", or eof
stores characters in line_save
returns:
EOF on empty line on end of file or
OK otherwise
*/
PHRQ_io::LINE_TYPE CParser::get_logical_line()
{
int
j;
unsigned int
pos;
char
c;
m_line_save.erase(m_line_save.begin(), m_line_save.end()); // m_line_save.clear();
while ((j = m_input_stream.get()) != std::char_traits < char >::eof())
{
c = (char) j;
if (c == '#')
{
// ignore all chars after # until newline
do
{
c = (char) j;
if (c == '\n')
{
break;
}
m_line_save += c;
}
while ((j =
m_input_stream.get()) != std::char_traits <
char >::eof());
}
if (c == ';')
break;
if (c == '\n')
{
break;
}
if (c == '\\')
{
pos = (int) m_line_save.size();
m_line_save += c;
while ((j =
m_input_stream.get()) != std::char_traits < char >::eof())
{
c = (char) j;
if (c == '\\')
{
pos = (int) m_line_save.size();
m_line_save += c;
continue;
}
if (c == '\n')
{
// remove '\\'
for (; pos < m_line_save.size(); pos++)
{
m_line_save[pos] = m_line_save[(size_t) pos + 1];
}
m_line_save.erase(m_line_save.size() - 1, 1);
break;
}
m_line_save += c;
if (!::isspace(j))
break;
}
}
else
{
m_line_save += c;
}
}
if (j == std::char_traits < char >::eof() && m_line_save.size() == 0)
{
return (PHRQ_io::LT_EOF);
}
return (PHRQ_io::LT_OK);
}
bool
CParser::check_key(std::string::iterator begin, std::string::iterator end)
{
std::string lowercase;
copy_token(lowercase, begin, end);
std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(),
tolower);
m_next_keyword = Keywords::Keyword_search(lowercase);
if (m_next_keyword == Keywords::KEY_NONE)
{
return false;
}
return true;
}
CParser::STATUS_TYPE CParser::check_units(std::string & tot_units,
bool alkalinity,
bool check_compatibility,
const std::string & default_units,
bool print)
{
/*
* Check if legitimate units
* Input:
* tot_units character string to check,
* alkalinity true if alkalinity, false if any other total,
* check_compatibility true check alk and default units, false otherwise
* default_units character string of default units (check /L, /kg, etc)
* print true print warning messages
* Output:
* tot_units standard form for unit
*/
using
Utilities::str_tolower;
using
Utilities::replace;
using
Utilities::squeeze_white;
static const char *
units[] = {
"Mol/l", /* 0 */
"mMol/l", /* 1 */
"uMol/l", /* 2 */
"g/l", /* 3 */
"mg/l", /* 4 */
"ug/l", /* 5 */
"Mol/kgs", /* 6 */
"mMol/kgs", /* 7 */
"uMol/kgs", /* 8 */
"g/kgs", /* 9 = ppt */
"mg/kgs", /* 10 = ppm */
"ug/kgs", /* 11 = ppb */
"Mol/kgw", /* 12 = mol/kg H2O */
"mMol/kgw", /* 13 = mmol/kg H2O */
"uMol/kgw", /* 14 = umol/kg H2O */
"g/kgw", /* 15 = mol/kg H2O */
"mg/kgw", /* 16 = mmol/kg H2O */
"ug/kgw", /* 17 = umol/kg H2O */
"eq/l", /* 18 */
"meq/l", /* 19 */
"ueq/l", /* 20 */
"eq/kgs", /* 21 */
"meq/kgs", /* 22 */
"ueq/kgs", /* 23 */
"eq/kgw", /* 24 */
"meq/kgw", /* 25 */
"ueq/kgw", /* 26 */
};
squeeze_white(tot_units);
str_tolower(tot_units);
replace("milli", "m", tot_units);
replace("micro", "u", tot_units);
replace("grams", "g", tot_units);
replace("gram", "g", tot_units);
replace("moles", "Mol", tot_units);
replace("mole", "Mol", tot_units);
replace("mol", "Mol", tot_units);
replace("liter", "l", tot_units);
replace("kgh", "kgw", tot_units);
replace("ppt", "g/kgs", tot_units);
replace("ppm", "mg/kgs", tot_units);
replace("ppb", "ug/kgs", tot_units);
replace("equivalents", "eq", tot_units);
replace("equivalent", "eq", tot_units);
replace("equiv", "eq", tot_units);
std::string::size_type end;
if ((end = tot_units.find("/l")) != std::string::npos)
{
tot_units.resize(end + 2);
}
if ((end = tot_units.find("/kgs")) != std::string::npos)
{
tot_units.resize(end + 4);
}
if ((end = tot_units.find("/kgw")) != std::string::npos)
{
tot_units.resize(end + 4);
}
//
// Check if unit in list
//
bool
found = false;
for (unsigned int i = 0; i < sizeof(units) / sizeof(char *); ++i)
{
if (tot_units.compare(units[i]) == 0)
{
found = true;
break;
}
}
if (!found)
{
if (print)
{
std::ostringstream err;
err << "Unknown unit, " << tot_units;
this->error_msg(err.str().c_str(), PHRQ_io::OT_CONTINUE);
}
return PARSER_ERROR;
}
//
// Check if units are compatible with default_units
//
if (check_compatibility == false)
return PARSER_OK;
//
// Special cases for alkalinity
//
if (alkalinity == true && tot_units.find("Mol") != std::string::npos)
{
if (print)
{
this->warning_msg
("Alkalinity given in moles, assumed to be equivalents.");
}
replace("Mol", "eq", tot_units);
}
if (alkalinity == false && tot_units.find("eq") != std::string::npos)
{
if (print)
{
this->error_msg("Only alkalinity can be entered in equivalents.",
PHRQ_io::OT_CONTINUE);
}
return PARSER_ERROR;
}
//
// See if default_units are compatible with tot_units
//
if (default_units.find("/l") != std::string::npos
&& tot_units.find("/l") != std::string::npos)
return PARSER_OK;
if (default_units.find("/kgs") != std::string::npos
&& tot_units.find("/kgs") != std::string::npos)
return PARSER_OK;
if (default_units.find("/kgw") != std::string::npos
&& tot_units.find("/kgw") != std::string::npos)
return PARSER_OK;
std::string str = default_units;
replace("kgs", "kg solution", str);
replace("kgs", "kg solution", tot_units);
replace("kgw", "kg water", str);
replace("kgw", "kg water", tot_units);
replace("/l", "/L", str);
replace("Mol", "mol", str);
replace("/l", "/L", tot_units);
replace("Mol", "mol", tot_units);
if (print)
{
std::ostringstream err;
err << "Units for master species, " << tot_units <<
", are not compatible with default units, " << str << ".";
this->error_msg(err.str().c_str(), PHRQ_io::OT_CONTINUE);
}
return PARSER_ERROR;
}
CParser::TOKEN_TYPE CParser::token_type(const std::string & token)
{
if (!token.empty())
{
if (::isupper(token[0]))
{
return CParser::TT_UPPER;
}
else if (::islower(token[0]))
{
return CParser::TT_LOWER;
}
else if (::isdigit(token[0]) || token[0] == '.' || token[0] == '-')
{
return CParser::TT_DIGIT;
}
else
{
assert(!::isspace(token[0]));
return CParser::TT_UNKNOWN;
}
}
else
{
return CParser::TT_EMPTY;
}
}
CParser::TOKEN_TYPE CParser::peek_token()
{
std::istringstream::pos_type pos = m_line_iss.tellg();
std::string token;
m_line_iss >> token;
m_line_iss.seekg(pos);
return token_type(token);
}
CParser::TOKEN_TYPE CParser::copy_token(std::string & token,
std::string::iterator & begin,
std::string::iterator & end)
{
if (begin != end)
{
std::string::iterator b = begin;
for (; b < end &&::isspace(*b); ++b);
begin = b;
for (; begin < end && !::isspace(*begin); ++begin);
token.assign(b, begin);
}
else
{
token.resize(0);
}
return token_type(token);
}
CParser::TOKEN_TYPE CParser::copy_token(std::string & token,
std::istream & is)
{
is >> token;
return token_type(token);
}
CParser::TOKEN_TYPE CParser::copy_token(std::string & token,
std::istream::pos_type & pos)
{
m_line_iss.seekg(pos);
if (!(m_line_iss >> token))
{
token.erase(token.begin(), token.end()); // token.clear();
}
pos = m_line_iss.tellg();
return token_type(token);
}
CParser::FIND_TYPE CParser::find_option(const std::string & item, int *n,
const std::vector < std::string >
&list, bool exact)
{
std::string token(item);
std::transform(token.begin(), token.end(), token.begin(), tolower);
for (unsigned int i = 0; i < list.size(); i++)
{
if (exact == true)
{
if (list[i].compare(token) == 0)
{
*n = i;
return FT_OK;
}
}
else
{
if (list[i].find(token) == 0)
{
*n = i;
return FT_OK;
}
}
}
*n = -1;
return FT_ERROR;
}
int
CParser::get_option(const std::vector < std::string > &opt_list,
std::string::iterator & next_char)
{
//
// Read a line and check for options
//
int j;
int /* opt_l, */ opt;
std::string::iterator opt_ptr;
std::string option;
#if !defined(R_SO)
fprintf(stderr, "Did not think this get_option was called\n");
#endif
//
// Read line
//
PHRQ_io::LINE_TYPE lt = check_line("get_option", false, true, true, true);
if (lt == PHRQ_io::LT_EOF)
{
j = OPT_EOF;
}
else if (lt == PHRQ_io::LT_KEYWORD)
{
j = OPT_KEYWORD;
}
else if (lt == PHRQ_io::LT_OPTION)
{
opt_ptr = m_line.begin();
std::string::iterator end = m_line.end();
copy_token(option, opt_ptr, end);
if (find_option(option, &opt, opt_list, false) == CParser::FT_OK)
{
j = opt;
m_line_save.replace(m_line_save.find(option), option.size(),
opt_list[opt]);
m_line.replace(m_line.find(option), option.size(), opt_list[opt]);
opt_ptr = m_line.begin();
std::string::iterator end = m_line.end();
copy_token(option, opt_ptr, end);
next_char = opt_ptr;
if (true) // pr.echo_input == TRUE
{
if (true) // database_file == NULL
{
//get_output() << "\t" << m_line_save << "\n";
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
io->output_msg(msg.str().c_str());
}
}
}
else
{
if (true) // (database_file == NULL)
{
//get_output() << "\t" << m_line_save << "\n";
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
io->output_msg(msg.str().c_str());
}
std::ostringstream err;
err << "Unknown option." << "\n";
err << m_line_save << "\n";
error_msg(err.str().c_str());
j = OPT_ERROR;
next_char = m_line.begin();
}
}
else
{
opt_ptr = m_line.begin();
std::string::iterator end = m_line.end();
copy_token(option, opt_ptr, end);
if (find_option(option, &opt, opt_list, true) == FT_OK)
{
j = opt;
next_char = opt_ptr;
}
else
{
j = OPT_DEFAULT;
next_char = m_line.begin();
}
if (true) // pr.echo_input == TRUE
{
if (true) // database_file == NULL
{
#if !defined(R_SO)
std::cout << "\t" << m_line_save << "\n";
#endif
}
}
}
return (j);
}
int
CParser::get_option(const std::vector < std::string > &opt_list,
std::istream::pos_type & next_pos)
{
//
// Read a line and check for options
//
int j;
int opt;
std::istream::pos_type pos_ptr;
std::string option;
//
// Read line
//
PHRQ_io::LINE_TYPE lt = check_line("get_option", false, true, true, true);
if (lt == PHRQ_io::LT_EOF)
{
j = OPT_EOF;
}
else if (lt == PHRQ_io::LT_KEYWORD)
{
j = OPT_KEYWORD;
}
else if (lt == PHRQ_io::LT_OPTION)
{
std::string::iterator opt_ptr = m_line.begin();
std::string::iterator end = m_line.end();
copy_token(option, opt_ptr, end);
if (find_option(option.substr(1), &opt, opt_list, false) == FT_OK)
{
// replace -option with option
j = opt;
m_line_save.replace(m_line_save.find(option), option.size(),
opt_list[opt]);
m_line.replace(m_line.find(option), option.size(), opt_list[opt]);
// reset iss
m_line_iss.str(m_line);
m_line_iss.seekg(0, std::ios_base::beg);
m_line_iss.clear();
pos_ptr = 0;
copy_token(option, pos_ptr);
next_pos = pos_ptr;
}
else
{
j = OPT_ERROR;
next_pos = pos_ptr;
}
}
else
{
pos_ptr = m_line_iss.tellg();
m_line_iss >> option;
if (find_option(option, &opt, opt_list, true) == FT_OK)
{
j = opt;
next_pos = m_line_iss.tellg();
}
else
{
j = OPT_DEFAULT;
m_line_iss.seekg(pos_ptr);
m_line_iss.clear();
next_pos = pos_ptr;
}
}
return (j);
}
CParser::STATUS_TYPE CParser::get_elt(std::string::iterator & begin,
const std::string::iterator end,
std::string & element)
{
element.erase(element.begin(), element.end()); // element.clear();
if (begin == end)
{
error_msg("Empty string in get_elt. Expected an element name.",
PHRQ_io::OT_CONTINUE);
return PARSER_ERROR;
}
//
// Load name into char array element
//
char
c = *begin;
++begin;
element.insert(element.end(), c); // element.push_back(c);
if (c == '[')
{
while ((c = *begin) != ']')
{
element.insert(element.end(), c); // element.push_back(c);
++begin;
if ((c = *begin) == ']')
{
element.insert(element.end(), c); // element.push_back(c);
++begin;
break;
}
else if (begin == end)
{
error_msg("No ending bracket (]) for element name",
PHRQ_io::OT_CONTINUE);
incr_input_error();
return PARSER_ERROR;
}
}
while (::islower(c = *begin) || c == '_')
{
element.insert(element.end(), c); // element.push_back(c);
++begin;
if (begin == end)
break;
}
}
else
{
while (::islower(c = *begin) || c == '_')
{
element.insert(element.end(), c); // element.push_back(c);
++begin;
if (begin == end)
break;
}
}
return PARSER_OK;
}
CParser::STATUS_TYPE CParser::parse_couple(std::string & token)
{
// Parse couple puts redox couples in standard form
// "+" is removed and couples are rewritten in sort
// order.
if (Utilities::strcmp_nocase_arg1(token.c_str(), "pe") == 0)
{
Utilities::str_tolower(token);
return PARSER_OK;
}
while (Utilities::replace("(+", "(", token));
std::string::iterator ptr = token.begin();
std::string elt1;
get_elt(ptr, token.end(), elt1);
if (*ptr != '(')
{
std::ostringstream err_msg;
err_msg << "Element name must be followed by " <<
"parentheses in redox couple, " << token << ".";
error_msg(err_msg.str().c_str(), PHRQ_io::OT_CONTINUE);
incr_input_error();
return PARSER_ERROR;
}
int
paren_count = 1;
std::string paren1 = "(";
while (ptr != token.end())
{
++ptr;
if (*ptr == '/' || ptr == token.end())
{
std::ostringstream err_msg;
err_msg << "End of line or " "/"
" encountered before end of parentheses, " << token << ".";
error_msg(err_msg.str().c_str(), PHRQ_io::OT_CONTINUE);
return PARSER_ERROR;
}
paren1.insert(paren1.end(), *ptr); // element.push_back(c);
if (*ptr == '(')
++paren_count;
if (*ptr == ')')
--paren_count;
if (paren_count == 0)
break;
}
++ptr;
if (ptr == token.end() || *ptr != '/')
{
std::ostringstream err_msg;
err_msg << " " "/" " must follow parentheses " <<
"ending first half of redox couple, " << token << ".";
error_msg(err_msg.str().c_str(), PHRQ_io::OT_CONTINUE);
return PARSER_ERROR;
}
++ptr;
std::string elt2;
get_elt(ptr, token.end(), elt2);
if (elt1.compare(elt2) != 0)
{
std::ostringstream err_msg;
err_msg << "Redox couple must be two redox states " <<
"of the same element, " << token << ".";
error_msg(err_msg.str().c_str(), PHRQ_io::OT_CONTINUE);
return PARSER_ERROR;
}
if (*ptr != '(')
{
std::ostringstream err_msg;
err_msg << "Element name must be followed by "
"parentheses in redox couple, " << token << ".";
error_msg(err_msg.str().c_str(), PHRQ_io::OT_CONTINUE);
incr_input_error();
return PARSER_ERROR;
}
std::string paren2 = "(";
paren_count = 1;
while (ptr != token.end())
{
++ptr;
if (*ptr == '/' || ptr == token.end())
{
std::ostringstream err_msg;
err_msg << "End of line or " "/"
" encountered before end of parentheses, " << token << ".";
error_msg(err_msg.str().c_str(), PHRQ_io::OT_CONTINUE);
return PARSER_ERROR;
}
paren2.insert(paren2.end(), *ptr); // element.push_back(c);
if (*ptr == '(')
++paren_count;
if (*ptr == ')')
--paren_count;
if (paren_count == 0)
break;
}
if (paren1.compare(paren2) < 0)
{
token = elt1 + paren1 + std::string("/") + elt2 + paren2;
}
else if (paren1.compare(paren2) > 0)
{
token = elt2 + paren2 + std::string("/") + elt1 + paren1;
}
else
{
std::ostringstream err_msg;
err_msg << "Both parts of redox couple are the same, " <<
token << ".";
error_msg(err_msg.str().c_str(), PHRQ_io::OT_CONTINUE);
return PARSER_ERROR;
}
return PARSER_OK;
}
template <class T>
CParser::STATUS_TYPE CParser::addPair(std::map < std::string, T >&totals,
std::istream::pos_type & pos)
{
std::string token;
T d;
CParser::TOKEN_TYPE j;
m_line_iss.seekg(pos);
j = copy_token(token, pos);
if (j == CParser::TT_EMPTY)
return PARSER_OK;
if (!(m_line_iss >> d))
{
return PARSER_ERROR;
}
totals[token] = d;
return PARSER_OK;
}
int
CParser::getOptionFromLastLine(const std::vector < std::string > &opt_list,
std::string::iterator & next_char, bool flag_error)
{
//
// Read a line and check for options
//
int j;
int /* opt_l, */ opt;
std::string::iterator opt_ptr;
std::string option;
//
// Read line
//
PHRQ_io::LINE_TYPE lt = m_line_type;
if (lt == PHRQ_io::LT_EOF)
{
j = OPT_EOF;
}
else if (lt == PHRQ_io::LT_KEYWORD)
{
j = OPT_KEYWORD;
}
else if (lt == PHRQ_io::LT_OPTION)
{
opt_ptr = m_line.begin();
std::string::iterator end = m_line.end();
copy_token(option, opt_ptr, end);
if (find_option(option, &opt, opt_list, false) == CParser::FT_OK)
{
j = opt;
m_line_save.replace(m_line_save.find(option), option.size(),
opt_list[opt]);
m_line.replace(m_line.find(option), option.size(), opt_list[opt]);
opt_ptr = m_line.begin();
std::string::iterator end = m_line.end();
copy_token(option, opt_ptr, end);
next_char = opt_ptr;
if (true) // pr.echo_input == TRUE
{
if (true) // database_file == NULL
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
io->output_msg(msg.str().c_str());
}
}
}
else
{
if (flag_error)
{
if (true) // (database_file == NULL)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
io->output_msg(msg.str().c_str());
}
std::ostringstream err;
err << "Unknown option." << "\n";
err << m_line_save << "\n";
error_msg(err.str().c_str());
}
j = OPT_ERROR;
next_char = m_line.begin();
}
}
else
{
opt_ptr = m_line.begin();
std::string::iterator end = m_line.end();
copy_token(option, opt_ptr, end);
if (find_option(option, &opt, opt_list, true) == FT_OK)
{
j = opt;
next_char = opt_ptr;
}
else
{
j = OPT_DEFAULT;
next_char = m_line.begin();
}
if (true) // pr.echo_input == TRUE
{
if (true) // database_file == NULL
{
#if !defined(R_SO)
std::cout << "\t" << m_line_save << "\n";
#endif
}
}
}
return (j);
}
int
CParser::getOptionFromLastLine(const std::vector < std::string > &opt_list,
std::istream::pos_type & next_pos, bool flag_error)
{
//
// Read a line and check for options
//
int j;
int opt;
std::istream::pos_type pos_ptr;
std::string option;
//
// Read line
//
PHRQ_io::LINE_TYPE lt = m_line_type;
if (lt == PHRQ_io::LT_EOF)
{
j = OPT_EOF;
}
else if (lt == PHRQ_io::LT_KEYWORD)
{
j = OPT_KEYWORD;
}
else if (lt == PHRQ_io::LT_OPTION)
{
std::string::iterator opt_ptr = m_line.begin();
std::string::iterator end = m_line.end();
copy_token(option, opt_ptr, end);
if (find_option(option.substr(1), &opt, opt_list, false) == FT_OK)
{
// replace -option with option
j = opt;
m_line_save.replace(m_line_save.find(option), option.size(),
opt_list[opt]);
m_line.replace(m_line.find(option), option.size(), opt_list[opt]);
// reset iss
m_line_iss.str(m_line);
m_line_iss.seekg(0, std::ios_base::beg);
m_line_iss.clear();
pos_ptr = 0;
copy_token(option, pos_ptr);
next_pos = pos_ptr;
//if (this->echo_file) // pr.echo_input == TRUE
if (false)
{
if (true) // database_file == NULL
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
io->output_msg(msg.str().c_str());
}
}
}
else
{
if (flag_error) // don`t throw error
{
if (true) // (database_file == NULL)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
io->output_msg(msg.str().c_str());
}
error_msg("Unknown option.", PHRQ_io::OT_CONTINUE);
error_msg(m_line_save.c_str(), PHRQ_io::OT_CONTINUE);
incr_input_error();
}
j = OPT_ERROR;
next_pos = pos_ptr;
}
}
else
{
pos_ptr = 0;
copy_token(option, pos_ptr);
if (find_option(option, &opt, opt_list, true) == FT_OK)
{
j = opt;
next_pos = pos_ptr;
}
else
{
j = OPT_DEFAULT;
next_pos = 0;
}
if (true) // pr.echo_input == TRUE
{
if (true) // database_file == NULL
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
io->output_msg(msg.str().c_str());
}
}
}
return (j);
}
int CParser::
incr_input_error()
{
return ++m_input_error;
}
CParser::TOKEN_TYPE CParser::copy_title(std::string & token,
std::string::iterator & begin,
std::string::iterator & end)
{
if (begin != end)
{
std::string::iterator b = begin;
std::string::iterator e = end;
for (; b < end && (::isspace(*b) || (*b == ',')); ++b);
begin = b;
if (*begin == '"')
{
begin = ++b;
for (; begin != end && !(*begin == '"'); ++begin);
e = begin;
if (begin != end && *begin == '"')
{
e = begin++;
}
}
else if (*begin == '\'')
{
begin = ++b;
for (; begin != end && !(*begin == '\''); ++begin);
e = begin;
if (begin != end && *begin == '\'')
{
e = begin++;
}
}
else
{
for (; begin < end && !(*begin == ',') && !(::isspace(*begin)); ++begin);
e = begin;
}
token.assign(b, e);
}
else
{
token.resize(0);
}
token = trim(token);
return token_type(token);
}
bool CParser::get_true_false(std::istream::pos_type & pos, bool def)
{
std::string token;
this->copy_token(token, pos);
std::string::iterator b = token.begin();
for (; b != token.end() && (::isspace(*b)); ++b);
if (b != token.end())
{
if (*b == 'f' || *b == 'F')
{
return false;
}
else if (*b == 't' || *b == 'T')
{
return true;
}
}
return def;
}
CParser::TOKEN_TYPE CParser::get_rest_of_line(std::string &token)
{
token.clear();
int j;
while ((j = m_line_iss.get()) != std::char_traits < char >::eof())
{
char c = (char) j;
token += c;
}
token = trim(token);
return token_type(token);
}
CParser::TOKEN_TYPE CParser::parse_delimited(std::string & source, std::string & result,
const std::string& t = " \t")
{
size_t pos = source.find_first_of(t);
std::string temp;
if (pos != std::string::npos)
{
result = source.substr(0, pos);
temp = source.substr(pos+1);
source = temp;
}
else
{
result = source;
source.clear();
}
std::string str = result;
return token_type(trim_left(str));
}