00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef NCL_NXSTOKEN_H
00021 #define NCL_NXSTOKEN_H
00022
00023 #include "ncl/nxsexception.h"
00024 class NxsToken;
00025
00026 class NxsX_UnexpectedEOF: public NxsException
00027 {
00028 public:
00029 NxsX_UnexpectedEOF(NxsToken &);
00030 };
00031
00032
00110 class NxsComment
00111 {
00112 public:
00113 NxsComment(const std::string & s, long lineNumber, long colNumber)
00114 :body(s),
00115 line(lineNumber),
00116 col(colNumber)
00117 {}
00118 long GetLineNumber() const
00119 {
00120 return line;
00121 }
00122 long GetColumnNumber() const
00123 {
00124 return col;
00125 }
00126 const std::string & GetText() const
00127 {
00128 return body;
00129 }
00130 void WriteAsNexus(std::ostream &out) const
00131 {
00132 out << '[' << body << ']';
00133 }
00134 private:
00135 std::string body;
00136 long line;
00137 long col;
00138 };
00139
00140
00144 class NxsTokenPosInfo
00145 {
00146 public:
00147 NxsTokenPosInfo()
00148 :pos(0),
00149 line(-1),
00150 col(-1)
00151 {}
00152 NxsTokenPosInfo(file_pos position, long lineno, long columnno)
00153 :pos(position),
00154 line(lineno),
00155 col(columnno)
00156 {}
00157 NxsTokenPosInfo(const NxsToken &);
00158
00159 file_pos GetFilePosition() const
00160 {
00161 return pos;
00162 }
00163
00164 long GetLineNumber() const
00165 {
00166 return line;
00167 }
00168
00169 long GetColumnNumber() const
00170 {
00171 return col;
00172 }
00173
00174
00175 file_pos pos;
00176 long line;
00177 long col;
00178 };
00179
00180
00187 class NxsSimpleCommandStrings
00188 {
00189 public:
00190 typedef std::vector<std::string> VecString;
00191 typedef std::list<VecString> MatString;
00192 typedef std::pair<NxsTokenPosInfo, std::string> SingleValFromFile;
00193 typedef std::pair<NxsTokenPosInfo, VecString > MultiValFromFile;
00194 typedef std::pair<NxsTokenPosInfo, MatString > MatFromFile;
00195 typedef std::map<std::string, SingleValFromFile> StringToValFromFile;
00196 typedef std::map<std::string, MultiValFromFile> StringToMultiValFromFile;
00197 typedef std::map<std::string, MatFromFile> StringToMatFromFile;
00198
00199
00200
00201
00202
00203 MultiValFromFile GetOptValue(const std::string &k) const
00204 {
00205 MultiValFromFile mvff;
00206 StringToValFromFile::const_iterator s = this->opts.find(k);
00207 if (s != this->opts.end())
00208 {
00209 const SingleValFromFile & v(s->second);
00210 mvff.first = v.first;
00211 mvff.second.push_back(v.second);
00212 }
00213 else
00214 {
00215 StringToMultiValFromFile::const_iterator m = this->multiOpts.find(k);
00216 if (m != this->multiOpts.end())
00217 {
00218 const MultiValFromFile & mv(m->second);
00219 mvff.first = mv.first;
00220 mvff.second = mv.second;
00221 }
00222 }
00223 return mvff;
00224 }
00225
00226 MatFromFile GetMatOptValue(const std::string & k) const
00227 {
00228 StringToMatFromFile::const_iterator mIt = this->matOpts.find(k);
00229 if (mIt == this->matOpts.end())
00230 return MatFromFile();
00231 return mIt->second;
00232 }
00233
00234 bool HasKey(const std::string k) const
00235 {
00236 if (this->opts.find(k) != this->opts.end())
00237 return true;
00238 return ((this->multiOpts.find(k) != this->multiOpts.end()) || (this->matOpts.find(k) != this->matOpts.end()));
00239 }
00240
00241 std::string cmdName;
00242 NxsTokenPosInfo cmdPos;
00243 StringToValFromFile opts;
00244 StringToMultiValFromFile multiOpts;
00245 StringToMatFromFile matOpts;
00246 };
00247
00251 class ProcessedNxsToken
00252 {
00253 public:
00254 static void IncrementNotLast(std::vector<ProcessedNxsToken>::const_iterator & it,
00255 const std::vector<ProcessedNxsToken>::const_iterator &endIt,
00256 const char * context);
00257 static NxsSimpleCommandStrings ParseSimpleCmd(const std::vector<ProcessedNxsToken> &, bool convertToLower);
00258
00259
00260 ProcessedNxsToken(const NxsToken &t);
00261
00262 ProcessedNxsToken(std::string &s)
00263 :token(s)
00264 {}
00265
00266 ProcessedNxsToken(std::string &s, file_pos position,long lineno, long columnno)
00267 :token(s),
00268 posInfo(position, lineno, columnno)
00269 {}
00270
00271 std::string GetToken() const
00272 {
00273 return token;
00274 }
00275
00276 const std::vector<NxsComment> & GetEmbeddedComments() const
00277 {
00278 return embeddedComments;
00279 }
00280
00281 NxsTokenPosInfo GetFilePosInfo() const
00282 {
00283 return posInfo;
00284 }
00285 const NxsTokenPosInfo & GetFilePosInfoConstRef() const
00286 {
00287 return posInfo;
00288 }
00289
00290 file_pos GetFilePosition() const
00291 {
00292 return posInfo.GetFilePosition();
00293 }
00294
00295 long GetLineNumber() const
00296 {
00297 return posInfo.GetLineNumber();
00298 }
00299
00300 long GetColumnNumber() const
00301 {
00302 return posInfo.GetColumnNumber();
00303 }
00304
00305 bool Equals(const char *c) const
00306 {
00307 return NxsString::case_insensitive_equals(token.c_str(), c);
00308 }
00309 bool EqualsCaseSensitive(const char *c) const
00310 {
00311 return (strcmp(token.c_str(), c) == 0);
00312 }
00313
00314 void SetEmbeddedComments(const std::vector<NxsComment> & c)
00315 {
00316 embeddedComments = c;
00317 }
00318
00319 void WriteAsNexus(std::ostream &out) const
00320 {
00321 for(std::vector<NxsComment>::const_iterator cIt = embeddedComments.begin(); cIt != embeddedComments.end(); ++cIt)
00322 cIt->WriteAsNexus(out);
00323 out << NxsString::GetEscaped(token);
00324 }
00325 private:
00326 std::string token;
00327 NxsTokenPosInfo posInfo;
00328 std::vector<NxsComment> embeddedComments;
00329 };
00330
00337 typedef std::vector<ProcessedNxsToken> ProcessedNxsCommand;
00338 bool WriteCommandAsNexus(std::ostream &, const ProcessedNxsCommand &);
00339
00340
00353 class NxsToken
00354 {
00355 public:
00356 static std::string EscapeString(const std::string &);
00357 static bool NeedsQuotes(const std::string &);
00358 static std::string GetQuoted(const std::string &);
00359 static void DemandEndSemicolon(NxsToken &token, NxsString & errormsg, const char *contextString);
00360 static unsigned DemandPositiveInt(NxsToken &token, NxsString & errormsg, const char *contextString);
00361 static std::map<std::string, std::string> ParseAsSimpleKeyValuePairs(const ProcessedNxsCommand & tv, const char *cmdName);
00362
00363 enum NxsTokenFlags
00364 {
00365 saveCommandComments = 0x0001,
00366 parentheticalToken = 0x0002,
00367 curlyBracketedToken = 0x0004,
00368 doubleQuotedToken = 0x0008,
00369 singleCharacterToken = 0x0010,
00370 newlineIsToken = 0x0020,
00371 tildeIsPunctuation = 0x0040,
00372 useSpecialPunctuation = 0x0080,
00373 hyphenNotPunctuation = 0x0100,
00374 preserveUnderscores = 0x0200,
00375 ignorePunctuation = 0x0400
00376 };
00377
00378 NxsString errormsg;
00379
00380 NxsToken(std::istream &i);
00381 virtual ~NxsToken();
00382
00383 bool AtEOF();
00384 bool AtEOL();
00385 bool Abbreviation(NxsString s);
00386 bool Begins(NxsString s, bool respect_case = false);
00387 void BlanksToUnderscores();
00388 bool Equals(NxsString s, bool respect_case = false) const;
00389 bool EqualsCaseSensitive(const char *c) const
00390 {
00391 return (strcmp(token.c_str(), c) == 0);
00392 }
00393
00394 long GetFileColumn() const;
00395 file_pos GetFilePosition() const;
00396 long GetFileLine() const;
00397 void GetNextToken();
00398 NxsString GetToken(bool respect_case = true);
00399 const char *GetTokenAsCStr(bool respect_case = true);
00400 const NxsString &GetTokenReference() const;
00401 int GetTokenLength() const;
00402 bool IsPlusMinusToken();
00403 bool IsPunctuationToken();
00404 bool IsWhitespaceToken();
00405 bool IsPlusMinusToken(const std::string & t);
00406 bool IsPunctuationToken(const std::string & t);
00407 bool IsWhitespaceToken(const std::string & t);
00408 std::map<std::string, std::string> ProcessAsSimpleKeyValuePairs(const char *cmdName);
00409 void ProcessAsCommand(ProcessedNxsCommand *tokenVec);
00410 void ReplaceToken(const NxsString s);
00411 void ResetToken();
00412 void SetSpecialPunctuationCharacter(char c);
00413 void SetLabileFlagBit(int bit);
00414 bool StoppedOn(char ch);
00415 void StripWhitespace();
00416 void ToUpper();
00417 void Write(std::ostream &out);
00418 void Writeln(std::ostream &out);
00419
00420 virtual void OutputComment(const NxsString &msg);
00421
00422 void SetEOFAllowed(bool e)
00423 {
00424 eofAllowed = e;
00425 }
00426 bool GetEOFAllowed() const
00427 {
00428 return eofAllowed;
00429 }
00430 void SetBlockName(const char *);
00431 std::string GetBlockName();
00432 const std::vector<NxsComment> & GetEmbeddedComments() const
00433 {
00434 return embeddedComments;
00435 }
00436 char PeekAtNextChar() const;
00437 protected:
00438
00439 void AppendToComment(char ch);
00440 void AppendToToken(char ch);
00441 bool GetComment();
00442 void GetCurlyBracketedToken();
00443 void GetDoubleQuotedToken();
00444 void GetQuoted();
00445 void GetParentheticalToken();
00446 bool IsPunctuation(char ch);
00447 bool IsWhitespace(char ch);
00448
00449 private:
00450 void AdvanceToNextCharInStream();
00451 char GetNextChar();
00452
00453
00454 std::istream &inputStream;
00455 signed char nextCharInStream;
00456 file_pos posOffBy;
00457 file_pos usualPosOffBy;
00458 long fileLine;
00459 long fileColumn;
00460 NxsString token;
00461 NxsString comment;
00462 bool eofAllowed;
00463 signed char saved;
00464 bool atEOF;
00465 bool atEOL;
00466 char special;
00467 int labileFlags;
00468 char whitespace[4];
00469 std::string currBlock;
00470 std::vector<NxsComment> embeddedComments;
00471 };
00472
00473 typedef NxsToken NexusToken;
00474
00475
00476 inline ProcessedNxsToken::ProcessedNxsToken(const NxsToken &t)
00477 :token(t.GetTokenReference()),
00478 posInfo(t)
00479 {}
00480
00481 inline NxsTokenPosInfo::NxsTokenPosInfo(const NxsToken &t)
00482 :pos(t.GetFilePosition()),
00483 line(t.GetFileLine()),
00484 col(t.GetFileColumn())
00485 {}
00486
00490 inline void NxsToken::SetBlockName(const char *c)
00491 {
00492 if (c == 0L)
00493 currBlock.clear();
00494 else
00495 currBlock.assign(c);
00496 }
00497
00501 inline std::string NxsToken::GetBlockName()
00502 {
00503 return currBlock;
00504 }
00505
00509 inline std::string NxsToken::EscapeString(const std::string &s)
00510 {
00511 return NxsString::GetEscaped(s);
00512 }
00513
00517 inline const NxsString &NxsToken::GetTokenReference() const
00518 {
00519 return token;
00520 }
00521
00529 inline void NxsToken::OutputComment(
00530 const NxsString &)
00531 {
00532 }
00533
00537 inline void NxsToken::AppendToComment(
00538 char ch)
00539 {
00540 comment += ch;
00541 }
00542
00546 inline void NxsToken::AppendToToken(
00547 char ch)
00548 {
00549 token.push_back(ch);
00550 }
00551
00568 inline bool NxsToken::IsPunctuation(
00569 char ch)
00570 {
00571
00572
00573
00574
00575 if (NxsString::IsNexusPunctuation(ch))
00576 {
00577 if (labileFlags & hyphenNotPunctuation)
00578 # if defined(NCL_VERSION_2_STYLE_HYPHEN) && NCL_VERSION_2_STYLE_HYPHEN
00579 return (ch != '-');
00580 # else
00581 return (ch != '-' && ch != '+');
00582 # endif
00583 return true;
00584 }
00585 if (labileFlags & tildeIsPunctuation && ch == '~')
00586 return true;
00587 return (labileFlags & useSpecialPunctuation && ch == special);
00588 }
00589
00594 inline bool NxsToken::IsWhitespace(
00595 char ch)
00596 {
00597 bool ws = false;
00598
00599
00600
00601 if (strchr(whitespace, ch) != NULL)
00602 ws = true;
00603
00604
00605
00606
00607 if (labileFlags & newlineIsToken && ch == '\n')
00608 ws = false;
00609
00610 return ws;
00611 }
00612
00617 inline bool NxsToken::AtEOF()
00618 {
00619 return atEOF;
00620 }
00621
00626 inline bool NxsToken::AtEOL()
00627 {
00628 return atEOL;
00629 }
00630
00635 inline void NxsToken::BlanksToUnderscores()
00636 {
00637 token.BlanksToUnderscores();
00638 }
00639
00644 inline long NxsToken::GetFileColumn() const
00645 {
00646 return fileColumn;
00647 }
00648
00654 inline file_pos NxsToken::GetFilePosition() const
00655 {
00656 return inputStream.rdbuf()->pubseekoff(0,std::ios::cur, std::ios::in) + posOffBy;
00657 }
00658
00663 inline long NxsToken::GetFileLine() const
00664 {
00665 return fileLine;
00666 }
00667
00673 inline NxsString NxsToken::GetToken(
00674 bool respect_case)
00675 {
00676 if (!respect_case)
00677 ToUpper();
00678
00679 return token;
00680 }
00681
00687 inline const char *NxsToken::GetTokenAsCStr(
00688 bool respect_case)
00689 {
00690 if (!respect_case)
00691 ToUpper();
00692
00693 return token.c_str();
00694 }
00695
00699 inline int NxsToken::GetTokenLength() const
00700 {
00701 return (int)token.size();
00702 }
00703
00707 inline bool NxsToken::IsPlusMinusToken()
00708 {
00709 return IsPlusMinusToken(token);
00710 }
00711
00715 inline bool NxsToken::IsPlusMinusToken(const std::string &t)
00716 {
00717 return (t.size() == 1 && ( t[0] == '+' || t[0] == '-') );
00718 }
00719
00724 inline bool NxsToken::IsPunctuationToken()
00725 {
00726 return IsPunctuationToken(token);
00727 }
00728
00733 inline bool NxsToken::IsPunctuationToken(const std::string &t)
00734 {
00735 return (t.size() == 1 && IsPunctuation(t[0]));
00736 }
00737
00738
00743 inline bool NxsToken::IsWhitespaceToken()
00744 {
00745 return IsWhitespaceToken(token);
00746 }
00747
00751 inline bool NxsToken::IsWhitespaceToken(const std::string &t)
00752 {
00753 return (t.size() == 1 && IsWhitespace( t[0]));
00754 }
00755
00759 inline void NxsToken::ReplaceToken(
00760 const NxsString s)
00761 {
00762 token = s;
00763 }
00764
00768 inline void NxsToken::ResetToken()
00769 {
00770 token.clear();
00771 embeddedComments.clear();
00772 }
00773
00779 inline void NxsToken::SetSpecialPunctuationCharacter(
00780 char c)
00781 {
00782 special = c;
00783 }
00784
00789 inline void NxsToken::SetLabileFlagBit(
00790 int bit)
00791 {
00792 labileFlags |= bit;
00793 }
00794
00807 inline bool NxsToken::StoppedOn(
00808 char ch)
00809 {
00810 if (saved == ch)
00811 return true;
00812 else
00813 return false;
00814 }
00815 inline char NxsToken::PeekAtNextChar() const
00816 {
00817 return nextCharInStream;
00818 }
00823 inline void NxsToken::Write(
00824 std::ostream &out)
00825 {
00826 out << token;
00827 }
00828
00833 inline void NxsToken::Writeln(
00834 std::ostream &out)
00835 {
00836 out << token << std::endl;
00837 }
00838
00839 inline std::map<std::string, std::string> NxsToken::ProcessAsSimpleKeyValuePairs(const char *cmdName)
00840 {
00841 ProcessedNxsCommand tokenVec;
00842 ProcessAsCommand(&tokenVec);
00843 return ParseAsSimpleKeyValuePairs(tokenVec, cmdName);
00844 }
00845
00850 inline bool NxsToken::Equals(
00851 NxsString s,
00852 bool respect_case) const
00853 {
00854 if (respect_case)
00855 return (strcmp(token.c_str(), s.c_str()) == 0);
00856 return NxsString::case_insensitive_equals(token.c_str(), s.c_str());
00857 }
00858
00859 #endif