20 enum symType { symNull, symNumber, symOp, symVar };
23 explicit Token(
enum symType type) : s(
""), t(type) {}
24 explicit Token() : s(
""), t(symNull) {}
28 typedef std::map<string,double>
symtab;
57 const char *
nWord(
const char *chKey,
64 while (isspace(*chKey))
69 const long lenkey = strlen(chKey);
72 bool atBoundary =
true, inQuote=
false;
73 for (
const char *ptr = chCard; *ptr; ++ptr)
83 if ( atBoundary && strncmp( ptr, chKey, lenkey) == 0 )
105 const bool lgAnyWhitespacePrecedesWord =
false;
107 if (lgAnyWhitespacePrecedesWord)
108 return isspace(c) ?
true : false ;
110 return (! isalpha(c) ) && c !=
'_';
128 std::string name(
"");
132 if (!(isalnum(c) || c ==
'_'))
177 " A filename or label must be specified within double quotes, but no quotes were encountered on this command.\n"
178 " Name must be surrounded by exactly two double quotes, like \"name.txt\". \n"
200 if( i0 == NULL || i1 == NULL )
209 chLabel = string(i0+1,i1);
242 fprintf(
ioQQQ,
" Unrecognized command. Key=\"%4.4s\". This is routine ParseCommands.\n",
270 fprintf(fp,
"Available commands are:\n\n");
271 long int i=0, l=0, len;
288 fprintf(fp,
"\n\nSorry, no further help available yet -- try Hazy.\n\n");
305 for( i=0; i<(int)
LIMELM; ++i )
323 fprintf(
ioQQQ,
" There is a problem on the following command line:\n" );
325 fprintf(
ioQQQ,
" A value for %s should have been on this line.\n Sorry.\n",chDesc );
383 else if(!
nMatch(
"LINE") )
405 "large, I shall probably crash. The value was %.2e\n",
450 if( lchr ==
'-' || lchr ==
'+' )
472 deque<Token> chTokens(0);
475 (isdigit(chr) || chr ==
'.' || chr ==
'-' || chr ==
'+'
476 || chr ==
'e' || chr ==
'E' || chr ==
'^' || chr ==
'*' || chr ==
'/'
480 if (chr ==
'^' || chr ==
'*' || chr ==
'/' )
482 chTokens.push_back(Token(Token::symOp));
483 chTokens.back().s += chr;
488 chTokens.push_back(Token(Token::symVar));
494 if (chTokens.size() == 0 || chTokens.back().t != Token::symNumber)
495 chTokens.push_back(Token(Token::symNumber));
496 chTokens.back().s += chr;
501 ASSERT (chTokens.size() != 0);
504 vector<double> valstack;
506 if (!lgParseOK || 1 != valstack.size())
508 fprintf(
ioQQQ,
" PROBLEM - syntax error in number or expression on line\n");
514 double value = valstack[0];
527 " input line too short to provide %ld character label\n"
528 "== %-80s ==\n", nchar,
m_card);
532 return string(
m_card).substr(0,nchar);
581 if ( chTokens.size() < 1)
584 if (Token::symNumber == chTokens[0].t)
586 valstack.push_back(atof(chTokens[0].s.c_str()));
587 chTokens.pop_front();
590 if (Token::symVar == chTokens[0].t)
592 symtab::const_iterator var = tab.find(chTokens[0].s);
593 if (var == tab.end())
595 fprintf(
ioQQQ,
"ERROR: No value found for variable $%s\n",
596 chTokens[0].s.c_str());
599 valstack.push_back(var->second);
600 chTokens.pop_front();
610 const double v2 = valstack.back();
612 const double v1 = valstack.back();
632 valstack.push_back(result);
641 vector<string> opstack;
647 if ( chTokens.size() == 0 )
650 if ( chTokens.size() < 2 )
653 if ( Token::symOp != chTokens[0].t ||
"^" != chTokens[0].s )
656 opstack.push_back(chTokens[0].s);
657 chTokens.pop_front();
663 while (!opstack.empty())
665 if (!
doop(valstack, opstack.back()))
677 if (!
ParseExp(chTokens, valstack, tab))
680 while ( chTokens.size() > 0 &&
681 Token::symOp == chTokens[0].t &&
682 (
"*" == chTokens[0].s ||
"/" == chTokens[0].s ) )
684 string op = chTokens[0].s;
685 chTokens.pop_front();
687 if (!
ParseExp(chTokens, valstack, tab))
690 if (!
doop(valstack, op))
708 size_t len = strlen(s2);
709 if (::strncmp(
m_card, s2, len) != 0)
712 while (isspace(
m_card[len-1]))
739 fprintf(
ioQQQ,
" Hit EOF while reading element list; use END to end list.\n" );
754 fprintf(
ioQQQ,
" There must be a two numbers on this line, or END.\n" );
761 fprintf(
ioQQQ,
" There must be a two numbers on this line, or END.\n" );
779 " at end of input term, error after '%s'\n",s.
value.c_str());
791 if (c !=
' ' && c !=
'\t')
880 " at end of input term\n");
905 fprintf(
ioQQQ,
"Parser error, character not recognized '%c'\n",
919 " Save %s hit EOF while reading list; use END to end list.\n" ,chName);
921 " This command requires either a species within quotes or the keyword ALL.\n" );
930 list.push_back(chTerm);
947 if (table.
nvals != 0)
949 fprintf(
ioQQQ,
" Warning: over-writing existing table\n" );
958 fprintf(
ioQQQ,
" No pairs entered - can\'t interpolate.\n Sorry.\n" );
982 NoNumb(
"radius, value pair on each line");
983 table.
dist.push_back( dist );
984 table.
val.push_back( val );
990 for(
long i=1; i < table.
nvals; i++ )
993 if( table.
dist[i] <= table.
dist[i-1] )
995 fprintf(
ioQQQ,
" Radii must be in increasing order. Sorry.\n" );
bool nMatch(const char *chKey) const
bool hasCommand(const char *s2)
Symbol maybeNumber(bool numOK, const Symbol &s)
NORETURN void TotalInsanity(void)
double getNumberCheckLogLinNegImplLog(const char *chDesc)
STATIC bool ParseProduct(deque< Token > &chTokens, vector< double > &valstack, const symtab &tab)
void readList(vector< string > &list, const char *chName)
int GetQuote(string &chLabel)
char m_card[INPUT_LINE_LENGTH]
bool isCommandComment(void) const
double getNumberDefaultAlwaysLog(const char *chDesc, double fdef)
STATIC bool ParseExpr(deque< Token > &chTokens, vector< double > &valstack, const symtab &tab)
bool isBoundaryChar(char c)
STATIC bool doop(vector< double > &valstack, const string &op)
void trimTrailingWhiteSpace(string &str)
NORETURN void StringError() const
double getNumberPlain(const char *chDesc)
char m_card_raw[INPUT_LINE_LENGTH]
t_elementnames elementnames
string StandardFluxUnit(void) const
const char * StandardEnergyUnit(void) const
const int INPUT_LINE_LENGTH
NORETURN void NoNumb(const char *chDesc) const
STATIC bool ParseExp(deque< Token > &chTokens, vector< double > &valstack, const symtab &tab)
const char * strchr_s(const char *s, int c)
long int GetElem(void) const
const char * nWord(const char *chKey) const
string getFirstChunk(long i)
string StandardFluxUnit(const char *chCard)
char chElementNameShort[LIMELM][CHARS_ELEMENT_NAME_SHORT]
const char * nWord(const char *chKey, const char *chCard)
STATIC double dist(long, realnum[], realnum[])
double getNumberCheckAlwaysLogLim(const char *chDesc, double flim)
void help(FILE *fp) const
const char * StandardEnergyUnit(const char *chCard)
NORETURN void Error(const char *msg) const
#define DEBUG_ENTRY(funcname)
STATIC bool ParseNumber(deque< Token > &chTokens, vector< double > &valstack, const symtab &tab)
double getNumberCheckAlwaysLog(const char *chDesc)
const CloudyCommand *const m_Commands
double getNumberDefault(const char *chDesc, double fdef)
std::map< string, double > symtab
int fprintf(const Output &stream, const char *format,...)
NORETURN void CommandError(void) const
void getPairs(vector< double > &a, vector< double > &b)
double pow(double x, int i)
int PrintLine(FILE *fp) const
std::string getVarName(void)
void readLaw(DepthTable &table)
double getNumberDefaultNegImplLog(const char *chDesc, double fdef)
std::map< string, double > m_symtab
bool isComment(void) const
double getNumberCheck(const char *chDesc)