00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "ncl/nxsdefs.h"
00021 #include "ncl/nxsblock.h"
00022 #include "ncl/nxsreader.h"
00023 #include <cstdlib>
00024 using namespace std;
00025
00026
00027
00028 #if !defined(IGNORE_NXS_ASSERT) && !defined(NDEBUG)
00029 void ncl_assertion_failed(char const * expr, char const * function, char const * file, long line)
00030 {
00031 # if defined (ASSERTS_TO_EXCEPTIONS)
00032 NxsString err;
00033 # else
00034 std::ostream & err(cerr);
00035 # endif
00036 err << "\nNCL assertion failed:";
00037 err << "\n expr: " << expr;
00038 err << "\n func: " << function;
00039 err << "\n file: " << file;
00040 err << "\n line: " << line ;
00041 # if defined (ASSERTS_TO_EXCEPTIONS)
00042 throw NxsNCLAPIException(err);
00043 # else
00044 std::cerr << std::endl;
00045 std::exit(1);
00046 # endif
00047 }
00048 #endif
00049
00050
00052
00053 unsigned NxsLabelToIndicesMapper::GetIndicesFromSets(const std::string &label,
00054 NxsUnsignedSet *inds,
00055 const NxsUnsignedSetMap & itemSets)
00056 {
00057 const unsigned labelLen = (unsigned)label.length();
00058 NxsUnsignedSetMap::const_iterator csIt = itemSets.begin();
00059 for (; csIt != itemSets.end(); ++csIt)
00060 {
00061 const NxsString & csLabel = csIt->first;
00062 if (labelLen == csLabel.length() && NxsString::case_insensitive_equals(label.c_str(), csLabel.c_str()))
00063 {
00064 const std::set<unsigned> & csSet = csIt->second;
00065 if (inds)
00066 inds->insert(csSet.begin(), csSet.end());
00067 return (unsigned)csSet.size();
00068 }
00069 }
00070 return 0;
00071 }
00072
00074 unsigned NxsLabelToIndicesMapper::GetIndicesFromSetOrAsNumber(const std::string &label,
00075 NxsUnsignedSet *inds,
00076 const NxsUnsignedSetMap & itemSets,
00077 const unsigned maxInd,
00078 const char * itemType)
00079 {
00080 unsigned n = GetIndicesFromSets(label, inds, itemSets);
00081 if (n > 0)
00082 return n;
00083 long i;
00084 if (!NxsString::to_long(label.c_str(), &i))
00085 {
00086 NxsString emsg;
00087 emsg << "Expecting a number or " << itemType << " label, found " << label;
00088 throw NxsException(emsg);
00089 }
00090 i--;
00091 if (i > (long)maxInd || i < 0)
00092 {
00093 NxsString emsg = "Expecting a ";
00094 emsg << itemType << " name or a number corresponding to a " << itemType << "\'s number (a number from 1 to ";
00095 emsg << maxInd + 1 << "). Found " << label;
00096 throw NxsException(emsg);
00097 }
00098 unsigned asu = (unsigned) (i);
00099 if (inds)
00100 inds->insert(asu);
00101 return 1;
00102 }
00103
00104 void NxsBlock::WarnDangerousContent(const std::string &s, const NxsToken &token)
00105 {
00106 if (nexusReader)
00107 nexusReader->NexusWarnToken(s, NxsReader::PROBABLY_INCORRECT_CONTENT_WARNING, token);
00108 else
00109 throw NxsException(s, token);
00110 }
00111
00112 void NxsBlock::WarnDangerousContent(const std::string &s, const ProcessedNxsToken &token)
00113 {
00114 if (nexusReader)
00115 nexusReader->NexusWarnToken(s, NxsReader::PROBABLY_INCORRECT_CONTENT_WARNING, token);
00116 else
00117 throw NxsException(s, token);
00118 }
00119 void NxsBlock::SkipCommand(NxsToken & token)
00120 {
00121 if (nexusReader)
00122 {
00123 errormsg = "Skipping command: ";
00124 errormsg << token.GetTokenReference();
00125 nexusReader->NexusWarnToken(errormsg, NxsReader::SKIPPING_CONTENT_WARNING, token);
00126 errormsg.clear();
00127 }
00128 if (!token.Equals(";"))
00129 SkippingCommand(token.GetToken());
00130 if (storeSkippedCommands)
00131 {
00132 ProcessedNxsCommand pnc;
00133 token.ProcessAsCommand(&pnc);
00134 skippedCommands.push_back(pnc);
00135 }
00136 else
00137 token.ProcessAsCommand(NULL);
00138 }
00139
00140 void NxsBlock::WriteSkippedCommands(std::ostream & out) const
00141 {
00142 for (list<ProcessedNxsCommand>::const_iterator cIt = skippedCommands.begin(); cIt != skippedCommands.end(); ++cIt)
00143 {
00144 if (WriteCommandAsNexus(out, *cIt))
00145 out << '\n';
00146 }
00147
00148 }
00149
00150
00151
00159 NxsBlock::NxsCommandResult NxsBlock::HandleBasicBlockCommands(NxsToken & token)
00160 {
00161 if (token.Equals("TITLE"))
00162 {
00163 HandleTitleCommand(token);
00164 return NxsBlock::NxsCommandResult(HANDLED_COMMAND);
00165 }
00166 if (false && token.Equals("BLOCKID"))
00167 {
00168 HandleBlockIDCommand(token);
00169 return NxsBlock::NxsCommandResult(HANDLED_COMMAND);
00170 }
00171 if (token.Equals("LINK") && this->ImplementsLinkAPI())
00172 {
00173 HandleLinkCommand(token);
00174 return NxsBlock::NxsCommandResult(HANDLED_COMMAND);
00175 }
00176 if (token.Equals("END") || token.Equals("ENDBLOCK"))
00177 {
00178 HandleEndblock(token);
00179 return NxsBlock::NxsCommandResult(STOP_PARSING_BLOCK);
00180 }
00181 return NxsBlock::NxsCommandResult(UNKNOWN_COMMAND);
00182 }
00183
00187 void NxsBlock::HandleTitleCommand(NxsToken & token)
00188 {
00189 token.GetNextToken();
00190 if (token.Equals(";"))
00191 GenerateUnexpectedTokenNxsException(token, "a title for the block");
00192 if (!title.empty() && nexusReader)
00193 {
00194 errormsg = "Multiple TITLE commands were encountered the title \"";
00195 errormsg += title;
00196 errormsg += "\" will be replaced by \"";
00197 errormsg += token.GetToken() ;
00198 errormsg += '\"';
00199 nexusReader->NexusWarnToken(errormsg, NxsReader::OVERWRITING_CONTENT_WARNING, token);
00200 errormsg.clear();
00201 }
00202 title = token.GetToken();
00203
00204 autoTitle = false;
00205 DemandEndSemicolon(token, "TITLE");
00206 }
00207
00211 void NxsBlock::HandleBlockIDCommand(NxsToken & token)
00212 {
00213 token.GetNextToken();
00214 if (token.Equals(";"))
00215 GenerateUnexpectedTokenNxsException(token, "an id for the block");
00216 blockIDString = token.GetToken();
00217 DemandEndSemicolon(token, "BLOCKID");
00218 }
00219
00249 void NxsBlock::HandleLinkCommand(NxsToken & )
00250 {
00251 throw NxsUnimplementedException("NxsBlock::HandleLinkCommand");
00252 }
00256 void NxsBlock::WriteBasicBlockCommands(std::ostream &out) const
00257 {
00258 WriteTitleCommand(out);
00259 WriteBlockIDCommand(out);
00260 if (this->ImplementsLinkAPI())
00261 WriteLinkCommand(out);
00262 }
00263
00268 NxsBlock::NxsBlock()
00269 :isEmpty(true),
00270 isEnabled(true),
00271 isUserSupplied(false),
00272 nexusReader(NULL),
00273 next(NULL),
00274 linkAPI(false),
00275 storeSkippedCommands(true)
00276 {
00277 }
00278
00279 void NxsBlock::DemandIsAtEquals(NxsToken &token, const char *contextString) const
00287 {
00288 if (!token.Equals("="))
00289 {
00290 errormsg = "Expecting '=' ";
00291 if (contextString)
00292 errormsg.append(contextString);
00293 errormsg << " but found " << token.GetToken() << " instead";
00294 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00295 }
00296 }
00297
00298 void NxsBlock::DemandEquals(ProcessedNxsCommand::const_iterator & tokIt, const ProcessedNxsCommand::const_iterator & endIt, const char *contextString) const
00299 {
00300 ++tokIt;
00301 if (tokIt == endIt)
00302 {
00303 errormsg = "Expecting '=' ";
00304 if (contextString)
00305 errormsg.append(contextString);
00306 errormsg << " but found ; instead";
00307 --tokIt;
00308 throw NxsException(errormsg, *tokIt);
00309 }
00310 if (!tokIt->Equals("="))
00311 {
00312 errormsg = "Expecting '=' ";
00313 if (contextString)
00314 errormsg.append(contextString);
00315 errormsg << " but found " << tokIt->GetToken() << " instead";
00316 throw NxsException(errormsg, *tokIt);
00317 }
00318 }
00319
00320
00328 void NxsBlock::GenerateNxsException(NxsToken &token, const char *message) const
00329 {
00330 if (message)
00331 errormsg = message;
00332 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00333 }
00334
00342 void NxsBlock::GenerateUnexpectedTokenNxsException(NxsToken &token, const char *expected) const
00343 {
00344 errormsg = "Unexpected token";
00345 if (expected)
00346 {
00347 errormsg += ". Expecting ";
00348 errormsg += expected;
00349 errormsg += ", but found: ";
00350 }
00351 else
00352 {
00353 errormsg += ": ";
00354 }
00355 errormsg += token.GetToken();
00356 throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00357 }
00358
00359
00360
00365 void NxsBlock::HandleEndblock(
00366 NxsToken &token)
00367 {
00368 DemandEndSemicolon(token, "END or ENDBLOCK");
00369 }
00370
00374 NxsBlock::~NxsBlock()
00375 {
00376 if (nexusReader)
00377 nexusReader->Detach(this);
00378 }
00379
00385 unsigned NxsBlock::CharLabelToNumber(
00386 NxsString) NCL_COULD_BE_CONST
00387 {
00388 return 0;
00389 }
00390
00397 void NxsBlock::Disable()
00398 {
00399 isEnabled = false;
00400 }
00401
00408 void NxsBlock::Enable()
00409 {
00410 isEnabled = true;
00411 }
00412
00419 bool NxsBlock::IsEnabled() NCL_COULD_BE_CONST
00420 {
00421 return isEnabled;
00422 }
00423
00430 bool NxsBlock::IsUserSupplied() NCL_COULD_BE_CONST
00431 {
00432 return isUserSupplied;
00433 }
00434
00440 bool NxsBlock::IsEmpty() NCL_COULD_BE_CONST
00441 {
00442 return isEmpty;
00443 }
00444
00448 NxsString NxsBlock::GetID() const
00449 {
00450 return id;
00451 }
00452
00460 void NxsBlock::Read(
00461 NxsToken &)
00462 {
00463 }
00464
00470 void NxsBlock::Reset()
00471 {
00472 title = std::string();
00473
00474 autoTitle = false;
00475
00476
00477 errormsg.clear();
00478 isEnabled = true;
00479 isEmpty = true;
00480 isUserSupplied = false;
00481 skippedCommands.clear();
00482
00483 }
00484
00488 void NxsBlock::Report(
00489 std::ostream &) NCL_COULD_BE_CONST
00490 {
00491 }
00492
00498 void NxsBlock::SkippingCommand(
00499 NxsString )
00500 {
00501 }
00502
00509 unsigned NxsBlock::TaxonLabelToNumber(
00510 NxsString ) const
00511 {
00512 return 0;
00513 }
00514
00519 VecBlockPtr NxsBlock::GetImpliedBlocks()
00520 {
00521 return VecBlockPtr();
00522 }
00523
00528 VecConstBlockPtr NxsBlock::GetImpliedBlocksConst() const
00529 {
00530 return VecConstBlockPtr();
00531 }
00532
00542 NxsBlock * NxsBlock::CloneBlock(
00543 NxsBlockMapper &
00544 ) const
00545 {
00546 throw NxsUnimplementedException(NxsString("CloneBlock"));
00547 }
00548
00553 void NxsBlock::WriteAsNexus(std::ostream &) const
00554 {
00555 throw NxsUnimplementedException(NxsString("NxsBlock::WriteAsNexus"));
00556 }
00557
00558 void NxsBlock::WriteTitleCommand(std::ostream &out) const
00559 {
00560 const std::string &t = this->GetInstanceName();
00561 if (t.length() > 0)
00562 out << " TITLE " << NxsString::GetEscaped(t) << ";\n";
00563 }
00564
00565 void NxsBlock::WriteBlockIDCommand(std::ostream &out) const
00566 {
00567 const std::string & t = this->blockIDString;
00568 if (t.length() > 0)
00569 out << " BLOCKID " << NxsString::GetEscaped(t) << ";\n";
00570 }
00571
00577 void NxsBlock::WriteLinkCommand(std::ostream &) const
00578 {
00579 throw NxsUnimplementedException("NxsBlock::WriteLinkCommand");
00580 }
00581
00582 std::string GetBlockIDTitleString(NxsBlock &b)
00583 {
00584 const std::string &t = b.GetInstanceName();
00585 std::string r = b.GetID();
00586 r.append(" block");
00587 if (t.length() > 0)
00588 {
00589 r.append(" (");
00590 r.append(t);
00591 r.append(")");
00592 }
00593 return r;
00594 }
00595
00599 bool NxsBlock::ImplementsLinkAPI() const
00600 {
00601 return this->linkAPI;
00602 }
00603
00611 void NxsBlock::SetImplementsLinkAPI(bool v)
00612 {
00613 this->linkAPI = v;
00614 }
00622 unsigned NxsBlock::DemandPositiveInt(NxsToken &token, const char *contextString) const
00623 {
00624 return NxsToken::DemandPositiveInt(token, this->errormsg, contextString);
00625 }
00626
00627 void NxsBlock::DemandEndSemicolon(NxsToken &token, const char *contextString) const
00628 {
00629 NxsToken::DemandEndSemicolon(token, this->errormsg, contextString);
00630 }
00631