iphreeqc/Parser.cxx
David L Parkhurst 3131740cfb Compiles as class, debug, and Release.
Requires recompilation of the entire solution for some reason.

git-svn-id: svn://136.177.114.72/svn_GW/phreeqcpp/trunk@3878 1feff8c3-07ed-0310-ac33-dd36852eb9cd
2009-12-08 22:12:42 +00:00

1334 lines
29 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 <iostream> // std::cout std::cerr
#include "Utils.h"
#if defined (PHREEQC_CLASS)
#include "Phreeqc.h"
#endif
#include "Parser.h"
#include "output.h"
//extern char *string_hsave(const char *str);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CParser::CParser(PHREEQC_PTR_ARG_COMMA std::istream & input):m_input_stream(input), m_output_stream(std::cout), m_error_stream(std::cerr),
m_input_error(0),
m_next_keyword(KT_NONE)
{
m_line_save.reserve(80);
m_line.reserve(80);
echo_file = EO_ALL;
echo_stream = EO_NONE;
accumulate = false;
}
CParser::CParser(PHREEQC_PTR_ARG_COMMA std::istream & input, std::ostream & output):m_input_stream(input), m_output_stream(output), m_error_stream(std::cerr),
m_input_error(0),
m_next_keyword(KT_NONE)
{
m_line_save.reserve(80);
m_line.reserve(80);
echo_file = EO_ALL;
echo_stream = EO_NONE;
accumulate = false;
}
CParser::CParser(PHREEQC_PTR_ARG_COMMA std::istream & input, std::ostream & output, std::ostream & error):m_input_stream(input), m_output_stream(output), m_error_stream(error),
m_input_error(0),
m_next_keyword(KT_NONE)
{
m_line_save.reserve(80);
m_line.reserve(80);
echo_file = EO_ALL;
echo_stream = EO_NONE;
accumulate = false;
}
CParser::~CParser()
{
}
CParser::LINE_TYPE CParser::check_line(const std::string & str,
bool allow_empty, bool allow_eof,
bool allow_keyword, bool print)
{
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 != LT_EOF)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
get_output() << msg;
}
break;
case EO_KEYWORDS:
if (i == LT_KEYWORD)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
get_output() << msg;
}
break;
case EO_NOKEYWORDS:
if (i != LT_KEYWORD && i != LT_EOF)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
get_output() << msg;
}
break;
}
// output for file
switch (this->echo_file)
{
case EO_NONE:
break;
case EO_ALL:
if (i != LT_EOF)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
PHREEQC_COOKIE output_msg(PHREEQC_NAME_SPACE OUTPUT_MESSAGE, "%s", msg.str().c_str());
}
break;
case EO_KEYWORDS:
if (i == LT_KEYWORD)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
PHREEQC_COOKIE output_msg(PHREEQC_NAME_SPACE OUTPUT_MESSAGE, "%s", msg.str().c_str());
}
break;
case EO_NOKEYWORDS:
if (i != LT_KEYWORD && i != LT_EOF)
{
std::ostringstream msg;
msg << "\t" << m_line_save << "\n";
PHREEQC_COOKIE output_msg(PHREEQC_NAME_SPACE OUTPUT_MESSAGE, "%s", msg.str().c_str());
}
break;
}
}
while (i == LT_EMPTY && allow_empty == false);
// Check eof
if (i == LT_EOF && allow_eof == false)
{
std::ostringstream msg;
msg << "Unexpected eof while reading " << str <<
"\nExecution terminated.\n";
error_msg(msg, OT_STOP);
}
// Check keyword
if (i == LT_KEYWORD && allow_keyword == false)
{
std::ostringstream msg;
msg << "Expected data for " << str <<
", but got a keyword ending data block.";
error_msg(msg, OT_CONTINUE);
incr_input_error();
}
m_line_type = i;
return i;
}
CParser::LINE_TYPE CParser::get_line()
{
CParser::LINE_TYPE return_value = LT_EMPTY;
while (return_value == LT_EMPTY)
{
//
// Eliminate all characters after # sign as a comment
//
//
// Get line, check for eof
//
if (get_logical_line() == LT_EOF)
{
if (!m_input_stream.eof())
{
error_msg("Reading input file.", OT_CONTINUE);
error_msg("istream::get() returned an error.", OT_STOP);
}
else
{
//{{MOD
m_line.erase(m_line.begin(), m_line.end()); // m_line.clear();
//}}MOD
m_next_keyword = KT_EOF;
return 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 ? LT_EMPTY : LT_OK);
}
//
// Determine return_value
//
if (return_value == LT_OK)
{
if (check_key(m_line.begin(), m_line.end()))
{
return_value = 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 = 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
*/
CParser::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[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 (LT_EOF);
}
return (LT_OK);
}
//bool CParser::check_key(const std::string::iterator ptr)
bool
CParser::check_key(std::string::iterator begin, std::string::iterator end)
{
static std::map < std::string, KEY_TYPE > s_keyword_map;
if (s_keyword_map.size() == 0)
{
s_keyword_map.insert(std::map < std::string,
KEY_TYPE >::value_type("solution_raw",
KT_SOLUTION_RAW));
s_keyword_map.insert(std::map < std::string,
KEY_TYPE >::value_type("exchange_raw",
KT_EXCHANGE_RAW));
s_keyword_map.insert(std::map < std::string,
KEY_TYPE >::value_type("gas_phase_raw",
KT_GASPHASE_RAW));
s_keyword_map.insert(std::map < std::string,
KEY_TYPE >::value_type("kinetics_raw",
KT_KINETICS_RAW));
s_keyword_map.insert(std::map < std::string,
KEY_TYPE >::value_type("equilibrium_phases_raw",
KT_PPASSEMBLAGE_RAW));
s_keyword_map.insert(std::map < std::string,
KEY_TYPE >::value_type("solid_solutions_raw",
KT_SSASSEMBLAGE_RAW));
s_keyword_map.insert(std::map < std::string,
KEY_TYPE >::value_type("surface_raw",
KT_SURFACE_RAW));
}
std::string lowercase;
copy_token(lowercase, begin, end);
std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(),
tolower);
m_next_keyword = KT_NONE;
std::map < std::string, KEY_TYPE >::iterator map_iter =
s_keyword_map.find(lowercase);
if (map_iter == s_keyword_map.end())
return false;
m_next_keyword = (*map_iter).second;
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;
error_msg(err, 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)
{
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)
{
error_msg("Only alkalinity can be entered in equivalents.",
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 << ".";
error_msg(err, 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);
// m_line_iss >> token;
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;
}
// OPTION_TYPE get_option(const char **opt_list, int count_opt_list, char **next_char)
// OPTION_TYPE CParser::get_option(const std::vector<std::string>& opt_list, std::string::iterator& next_char)
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;
//char *opt_ptr;
std::string::iterator opt_ptr;
// char option[MAX_LENGTH];
std::string option;
fprintf(stderr, "Did not think this get_option was called\n");
//
// Read line
//
LINE_TYPE lt = check_line("get_option", false, true, true, true);
if (lt == LT_EOF)
{
j = OPT_EOF;
}
else if (lt == LT_KEYWORD)
{
j = OPT_KEYWORD;
}
else if (lt == 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";
}
}
}
else
{
if (true) // (database_file == NULL)
{
get_output() << "\t" << m_line_save << "\n";
}
//////std::istringstream err_msg;
//////err_msg << "Unknown option.";
//////err_msg << line_save;
//////error_msg(const std::string& msg, ONERROR_TYPE);
// error_msg("Unknown option.", CONTINUE);
// error_msg(line_save, CONTINUE);
// input_error++;
std::cerr << "Unknown option." << "\n";
std::cerr << m_line_save << "\n";
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
{
std::cout << "\t" << m_line_save << "\n";
}
}
}
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
//
LINE_TYPE lt = check_line("get_option", false, true, true, true);
if (lt == LT_EOF)
{
j = OPT_EOF;
}
else if (lt == LT_KEYWORD)
{
j = OPT_KEYWORD;
}
else if (lt == 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;
//{{
//// m_line_iss.clear();
//}}
/*
if (true) // pr.echo_input == TRUE
{
if (true) // database_file == NULL
{
get_output() << "\t" << m_line_save << "\n";
}
}
*/
}
else
{
/*
if (true) // (database_file == NULL)
{
get_output() << "\t" << m_line_save << "\n";
}
*/
//error_msg("Unknown option.", OT_CONTINUE);
//error_msg(m_line_save.c_str(), 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;
//}
//std::istringstream m_line_iss_copy = m_line_iss;
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;
//m_line_iss >> option;
}
/*
if (true) // pr.echo_input == TRUE
{
if (true) // database_file == NULL
{
fprintf(stderr, "Yikes 3\n");
get_output() << "\t" << m_line_save << "\n";
}
}
*/
}
return (j);
}
int
CParser::error_msg(const char *err_str, ONERROR_TYPE ot)
{
ERROR_MESSAGE_QUALIFIER error_msg(err_str, (int) ot);
m_error_stream << "ERROR: " << err_str << "\n";
m_error_stream.flush();
m_output_stream << "ERROR: " << err_str << "\n";
m_output_stream.flush();
if (ot == OT_STOP)
{
exit(1);
}
return 0;
}
int
CParser::warning_msg(const char *err_str)
{
m_error_stream << "WARNING: " << err_str << "\n";
m_error_stream.flush();
m_output_stream << "WARNING: " << err_str << "\n";
m_output_stream.flush();
return 0;
}
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.",
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",
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, 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, 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, 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, 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, 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, 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, OT_CONTINUE);
return PARSER_ERROR;
}
return PARSER_OK;
}
//CParser::STATUS_TYPE CParser::addPair(std::map < char *, double,
// CHARSTAR_LESS > &totals,
// std::istream::pos_type & pos)
//{
// std::string token;
// char *
// ctoken;
// double
// d;
//
// CParser::TOKEN_TYPE j;
//
// m_line_iss.seekg(pos);
//
// j = copy_token(token, pos);
//
// if (j == TT_EMPTY)
// return PARSER_OK;
//
// if (!(m_line_iss >> d))
// {
// return PARSER_ERROR;
// }
// ctoken = string_hsave(token.c_str());
// totals[ctoken] = d;
// return PARSER_OK;
//}
CParser::STATUS_TYPE CParser::addPair(std::map < std::string, double >&totals,
std::istream::pos_type & pos)
{
std::string token;
//char * ctoken;
double
d;
CParser::TOKEN_TYPE j;
m_line_iss.seekg(pos);
j = copy_token(token, pos);
if (j == TT_EMPTY)
return PARSER_OK;
if (!(m_line_iss >> d))
{
return PARSER_ERROR;
}
//ctoken = string_hsave(token.c_str());
//totals[ctoken] = d;
totals[token] = d;
return PARSER_OK;
}
int
CParser::getOptionFromLastLine(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;
//char *opt_ptr;
std::string::iterator opt_ptr;
// char option[MAX_LENGTH];
std::string option;
//
// Read line
//
LINE_TYPE lt = m_line_type;
if (lt == LT_EOF)
{
j = OPT_EOF;
}
else if (lt == LT_KEYWORD)
{
j = OPT_KEYWORD;
}
else if (lt == 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";
}
}
}
else
{
if (true) // (database_file == NULL)
{
get_output() << "\t" << m_line_save << "\n";
}
//////std::istringstream err_msg;
//////err_msg << "Unknown option.";
//////err_msg << line_save;
//////error_msg(const std::string& msg, ONERROR_TYPE);
// error_msg("Unknown option.", CONTINUE);
// error_msg(line_save, CONTINUE);
// input_error++;
std::cerr << "Unknown option." << "\n";
std::cerr << m_line_save << "\n";
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
{
std::cout << "\t" << m_line_save << "\n";
}
}
}
return (j);
}
int
CParser::getOptionFromLastLine(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
//
//LINE_TYPE lt = check_line("get_option", false, true, true, false);
LINE_TYPE lt = m_line_type;
if (lt == LT_EOF)
{
j = OPT_EOF;
}
else if (lt == LT_KEYWORD)
{
j = OPT_KEYWORD;
}
else if (lt == 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;
//{{
//// m_line_iss.clear();
//}}
if (true) // pr.echo_input == TRUE
{
if (true) // database_file == NULL
{
get_output() << "\t" << m_line_save << "\n";
}
}
}
else
{
if (true) // (database_file == NULL)
{
get_output() << "\t" << m_line_save << "\n";
}
error_msg("Unknown option.", OT_CONTINUE);
error_msg(m_line_save.c_str(), 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
{
get_output() << "\t" << m_line_save << "\n";
}
}
}
return (j);
}
int CParser::
incr_input_error()
{
++ ERROR_MESSAGE_QUALIFIER input_error;
return ++m_input_error;
}