/*---------------------------------------------------------------------------------------------------------------------- | This function provides the ability to read everything following the block name (which is read by the NxsReader | object) to the END or ENDBLOCK statement. Characters are read from the input stream `in'. Overrides the pure | virtual function in the base class. */ void NxsEmptyBlock::Read( NxsToken &token) /* the token used to read from `in'*/ { isEmpty = false; // This should be the semicolon after the block name // token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' after "; errormsg += id; errormsg += " block name, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } for(;;) { token.GetNextToken(); if (token.Equals("END")) { HandleEndblock(token); break; } else if(token.Equals("ENDBLOCK")) { HandleEndblock(token); break; } else { SkippingCommand(token.GetToken()); do { token.GetNextToken(); } while (!token.AtEOF() && !token.Equals(";")); if (token.AtEOF()) { errormsg = "Unexpected end of file encountered"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } } }
/*---------------------------------------------------------------------------------------------------------------------- | Called when the HELP command needs to be parsed from within the GarliReader block. */ void GarliReader::HandleHelp( NxsToken &token) /* the token used to read from `in' */ { // Retrieve all tokens for this command, stopping only in the event // of a semicolon or an unrecognized keyword // for (;;) { token.GetNextToken(); if (token.Equals(";")) { break; } else { errormsg = "Unexpected keyword ("; errormsg += token.GetToken(); errormsg += ") encountered reading HELP command"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } message = "\nExamples of use of available commands:"; message += "\n help -> shows this message"; message += "\n log file=mylog.txt start -> opens log file named mylog.txt"; message += "\n log stop -> closes current log file"; message += "\n exe mydata.nex -> executes nexus file mydata.nex"; message += "\n show -> reports on blocks currently stored"; message += "\n quit -> terminates application"; message += "\n"; PrintMessage(); }
/*---------------------------------------------------------------------------------------------------------------------- | Tries to interpret `token' as a number. Failing that, tries to interpret `token' as a character or taxon label, | which it then converts to a number. Failing that, it throws a NxsException exception. */ unsigned NxsSetReader::GetTokenValue() { unsigned v = atoi(token.GetToken().c_str()); if (v == 0 && settype != NxsSetReader::generic) { if (settype == NxsSetReader::charset) v = block.CharLabelToNumber(token.GetToken()); else if (settype == NxsSetReader::taxset) v = block.TaxonLabelToNumber(token.GetToken()); } if (v == 0) { block.errormsg = "Set element ("; block.errormsg += token.GetToken(); block.errormsg += ") not a number "; if (settype == NxsSetReader::charset) block.errormsg += "and not a valid character label"; else if (settype == NxsSetReader::taxset) block.errormsg += "and not a valid taxon label"; throw NxsException(block.errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } return v; }
/*---------------------------------------------------------------------------------------------------------------------- | Advances the token, and returns the unsigned int that the token represents | | Sets errormsg and raises a NxsException on failure. | `contextString` is used in error messages: | "Expecting ';' to terminate the ${contextString} command" */ void NxsToken::DemandEndSemicolon(NxsToken &token, NxsString & errormsg, const char *contextString) { token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' to terminate the "; errormsg += contextString; errormsg += " command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } }
/*---------------------------------------------------------------------------------------------------------------------- | Advances the token, and returns the unsigned int that the token represents | | Sets errormsg and raises a NxsException on failure. | `contextString` is used in error messages: | "${contextString} must be a number greater than 0" */ unsigned NxsToken::DemandPositiveInt(NxsToken &token, NxsString & errormsg, const char *contextString) { token.GetNextToken(); int i = atoi(token.GetToken().c_str()); if (i <= 0) { errormsg.assign(contextString); errormsg += " must be a number greater than 0. Found"; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } return (unsigned) i; }
/*---------------------------------------------------------------------------------------------------------------------- | Called when the END or ENDBLOCK command needs to be parsed from within the GarliReader block. Basically just | checks to make sure the next token in the data file is a semicolon. */ void GarliBlock::HandleEndblock( NxsToken &token) /* the token used to read from `in' */ { // Get the semicolon following END or ENDBLOCK token // token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' to terminate the END or ENDBLOCK command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } }
bool NxsFilePath::IsDirectory() const { if (!this->Exists()) return false; const char *const natDirName = this->GetNative().c_str(); struct NCL_STAT_STRUCT dStat; if (NCL_STAT(natDirName, &dStat) != 0) { std::string msg; msg += "stat call failed for "; msg += natDirName; throw NxsException(msg); } bool retCode = NCL_S_ISDIR(dStat.st_mode); //std::cerr << "IsDirectory is returning "<< retCode << " for " << natDirName <<std::endl; return retCode; }
/*---------------------------------------------------------------------------------------------------------------------- | Called whenever a file name needs to be read from either the command line or a file. Expects next token to be "=" | followed by the token representing the file name. Call this function after, say, the keyword "file" has been read | in the following LOG command: |> | log file=doofus.txt start replace; |> | Note that this function will read only the "=doofus.txt " leaving "start replace;" in the stream for reading at | a later time. */ NxsString GarliReader::GetFileName( NxsToken &token) /* the token used to read from `in' */ { // Eat the equals sign // token.GetNextToken(); if (!token.Equals("=")) { errormsg = "Expecting an equals sign, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } // Now get the filename itself // token.GetNextToken(); return token.GetToken(); }
/*---------------------------------------------------------------------------------------------------------------------- | Called when the LOG command needs to be parsed from within the GarliReader block. */ void GarliReader::HandleLog( NxsToken &token) /* the token used to read from `in' */ { bool starting = false; bool stopping = false; bool appending = false; bool replacing = false; bool name_provided = false; NxsString logfname; // Retrieve all tokens for this command, stopping only in the event // of a semicolon or an unrecognized keyword // for (;;) { token.GetNextToken(); if (token.Equals(";")) { break; } else if (token.Abbreviation("STOp")) { stopping = true; } else if (token.Abbreviation("STArt")) { starting = true; } else if (token.Abbreviation("Replace")) { replacing = true; } else if (token.Abbreviation("Append")) { appending = true; } else if (token.Abbreviation("File")) { logfname = GetFileName(token); name_provided = true; } else { errormsg = "Unexpected keyword ("; errormsg += token.GetToken(); errormsg += ") encountered reading LOG command"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } // Check for incompatible combinations of keywords // if (stopping && (starting || appending || replacing || name_provided)) { errormsg = "Cannot specify STOP with any of the following START, APPEND, REPLACE, FILE"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } if (appending && replacing) { errormsg = "Cannot specify APPEND and REPLACE at the same time"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } if (logf_open && (starting || name_provided || appending || replacing)) { errormsg = "Cannot start log file since log file is already open"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } // Is user closing an open log file? // if (stopping) { logf.close(); logf_open = false; message = "\nLog file closed"; PrintMessage(); return; } // If this far, must be attempting to open a log file // if (!name_provided) { errormsg = "Must provide a file name when opening a log file\n"; errormsg += "e.g., log file=doofus.txt start replace;"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } if (appending) { logf_open = true; logf.open(logfname.c_str(), ios::out | ios::app); message = "\nAppending to log file "; message += logfname; PrintMessage(); } else if (replacing) { logf_open = true; logf.open(logfname.c_str()); message = "\nReplacing log file "; message += logfname; PrintMessage(); } else { bool exists = FileExists(logfname.c_str()); bool userok = true; if (exists && !UserQuery("Ok to replace?", "Log file specified already exists", GarliReader::UserQueryEnum(GarliReader::uq_yes | GarliReader::uq_no))) userok = false; if (userok) { logf_open = true; logf.open(logfname.c_str()); } if (exists && userok) { message = "\nReplacing log file "; message += logfname; } else if (userok) { message = "\nLog file "; message += logfname; message += " opened"; } else { message = "\nLog command aborted"; } PrintMessage(); } }
/*---------------------------------------------------------------------------------------------------------------------- | Handles everything after the EXECUTE keyword and the terminating semicolon. Purges all blocks before executing | file specified, and no warning is given of this. | DJZ THIS IS NOT THE VERSION OF HandleExecute USED. See the other overloaded version below. */ void GarliReader::HandleExecute( NxsToken &token) /* the token used to read from `in' */ { // Issuing the EXECUTE command from within a file is a no-no (at least in this program) // if (inf_open) { errormsg = "Cannot issue execute command from within a GarliReader block"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } // Get the file name to execute (note: if filename contains underscores, these will be // automatically converted to spaces; user should surround such filenames with single quotes) // token.GetNextToken(); NxsString fn = token.GetToken(); // Get the semicolon terminating the EXECUTE command // token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' to terminate the EXECUTE command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } if (FileExists(fn.c_str())) { cerr << endl; cerr << "Opening " << fn << "..." << endl; ifstream inf(fn.c_str(), ios::binary | ios::in); inf_open = true; MyNexusToken ftoken(inf); try { Execute(ftoken); } catch(NxsException x) { NexusError(errormsg, x.pos, x.line, x.col); } if (inf_open) inf.close(); inf_open = false; // Users are allowed to put DATA blocks in their NEXUS files, but internally the data is always // stored in a NxsCharacterBlock object. // if (characters->IsEmpty() && !data->IsEmpty()) { data->TransferTo(*characters); } } // if (FileExists(fn.c_str())) else { cerr << endl; cerr << "Oops! Could not find specified file: " << fn << endl; } }
/*---------------------------------------------------------------------------------------------------------------------- | This function provides the ability to read everything following the block name (which is read by the NxsReader | object) to the END or ENDBLOCK statement. Characters are read from the input stream `in'. Overrides the virtual | function in the base class. */ void GarliBlock::Read( NxsToken &token) /* the token used to read from `in' */ { isEmpty = false; //if we already read a garli block with a model string, clear it modelString.clear(); // This should be the semicolon after the block name // token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' after "; errormsg += id; errormsg += " block name, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } for (;;) {//only allowing three things to happen here //1. endblock is reached, sucessfully exiting the garli block //2. something besides an endblock is read. This is interpreted as part of the model string, with minimal error checking //3. eof is hit before an endblock token.GetNextToken(); if (token.Abbreviation("ENdblock")) { HandleEndblock(token); break; } else if(token.AtEOF() == false){ NxsString s = token.GetToken(); if(s.size() > 1 && (s.IsADouble() == false && s.IsALong() == false)){ errormsg = "Unexpected character(s) in Garli block.\n See manual for model parameter format."; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } if(token.IsPunctuationToken() == false){//toss semicolons and such modelString += token.GetToken(); modelString += ' '; } } else { errormsg = "Unexpected end of file encountered before \"end;\" or\n \"endblock;\" command in Garli block"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } /* else if (token.Abbreviation("GarliReader")) { HandleGarliReader(token); } else if (token.Abbreviation("Help")) { HandleHelp(token); } else if (token.Abbreviation("Log")) { HandleLog(token); } else if (token.Abbreviation("EXecute")) { HandleExecute(token); } else if (token.Abbreviation("Show")) { HandleShow(token); } else if (token.Abbreviation("Quit")) { quit_now = true; message = "\nGarliReader says goodbye\n"; PrintMessage(); break; } else { SkippingCommand(token.GetToken()); do { token.GetNextToken(); } while (!token.AtEOF() && !token.Equals(";")); if (token.AtEOF()) { errormsg = "Unexpected end of file encountered"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } */ }
/*---------------------------------------------------------------------------------------------------------------------- | Reads rest of comment (starting '[' already input) and acts accordingly. If comment is an output comment, and if | an output stream has been attached, writes the output comment to the output stream. Otherwise, output comments are | simply ignored like regular comments. If the labileFlag bit saveCommandComments is in effect, the comment (without | the square brackets) will be stored in token. */ void NxsToken::GetComment() { // Set comment level to 1 initially. Every ']' encountered reduces // level by one, so that we know we can stop when level becomes 0. // int level = 1; // Get first character // char ch = GetNextChar(); if (atEOF) { errormsg = "Unexpected end of file inside comment"; throw NxsException( errormsg, GetFilePosition(), GetFileLine(), GetFileColumn()); } // See if first character is the output comment symbol ('!') // or command comment symbol (&) // int printing = 0; int command = 0; if (ch == '!') printing = 1; else if (ch == '&' && labileFlags & saveCommandComments) { command = 1; AppendToToken(ch); } else if (ch == ']') return; // Now read the rest of the comment // for(;;) { ch = GetNextChar(); if (atEOF) break; if (ch == ']') level--; else if (ch == '[') level++; if (level == 0) break; if (printing) AppendToComment(ch); else if (command) AppendToToken(ch); } if (printing) { // Allow output comment to be printed or displayed in most appropriate // manner for target operating system // OutputComment(comment); } }
/*---------------------------------------------------------------------------------------------------------------------- | Reads in a set from a NEXUS data file. Returns true if the set was terminated by a semicolon, false otherwise. */ bool NxsSetReader::Run() { bool ok; bool retval = false; unsigned rangeBegin = UINT_MAX; unsigned rangeEnd = rangeBegin; bool insideRange = false; unsigned modValue = 0; for (;;) { // Next token should be one of the following: // ';' --> set definition finished // '-' --> range being defined // <integer> --> member of set (or beginning or end of a range) // '.' --> signifies the number max // '\' --> signifies modulus value coming next // token.GetNextToken(); if (token.Equals("-")) { // We should not be inside a range when we encounter a hyphenation symbol. // The hyphen is what _puts_ us inside a range! // if (insideRange) { block.errormsg = "The symbol '-' is out of place here"; throw NxsException(block.errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } insideRange = true; } else if (token.Equals(".")) { // We _should_ be inside a range if we encounter a period, as this // is a range termination character // if (!insideRange) { block.errormsg = "The symbol '.' can only be used to specify the end of a range"; throw NxsException(block.errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } rangeEnd = max; } else if (token.Equals("\\")) { // The backslash character is used to specify a modulus to a range, and // thus should only be encountered if currently inside a range // if (!insideRange) { block.errormsg = "The symbol '\\' can only be used after the end of a range has been specified"; throw NxsException(block.errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } // This should be the modulus value // modValue = NxsToken::DemandPositiveInt(token, block.errormsg, "The modulus value"); } else if (insideRange && rangeEnd == UINT_MAX) { // The beginning of the range and the hyphen symbol have been read // already, just need to store the end of the range at this point // rangeEnd = GetTokenValue(); } else if (insideRange) { // If insideRange is true, we must have already stored the beginning // of the range and read in the hyphen character. We would not have // made it this far if we had also not already stored the range end. // Thus, we can go ahead and add the range. // ok = AddRange(rangeBegin, rangeEnd, modValue); if (!ok) { block.errormsg = "Character number out of range (or range incorrectly specified) in set specification"; throw NxsException(block.errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } // We have actually already read in the next token, so deal with it // now so that we don't end up skipping a token // if (token.Equals(";")) { retval = true; break; } else if (token.Equals(",")) { break; } rangeBegin = GetTokenValue(); rangeEnd = UINT_MAX; insideRange = false; } else if (rangeBegin != UINT_MAX) { // If we were inside a range, we would have not gotten this far. // If not in a range, we are either getting ready to begin a new // range or have previously read in a single value. Handle the // latter possibility here. // ok = AddRange(rangeBegin, rangeBegin, modValue); if (!ok) { block.errormsg = "Character number out of range (or range incorrectly specified) in set specification"; throw NxsException(block.errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } if (token.Equals(";")) { retval = true; break; } else if (token.Equals(",")) { break; } rangeBegin = GetTokenValue(); rangeEnd = UINT_MAX; } else if (token.Equals(";")) { retval = true; break; } else if (token.Equals(",")) { break; } else if (token.Equals("ALL")) { rangeBegin = 1; rangeEnd = max; ok = AddRange(rangeBegin, rangeEnd); } else { // Can only get here if rangeBegin still equals UINT_MAX and thus we // are reading in the very first token and that token is neither // the word "all" nor is it a semicolon // rangeBegin = GetTokenValue(); rangeEnd = UINT_MAX; } } return retval; }
/*---------------------------------------------------------------------------------------------------------------------- | This function provides the ability to read everything following the block name (which is read by the NxsReader | object) to the END or ENDBLOCK statement. Characters are read from the input stream `in'. Overrides the virtual | function in the base class. */ void GarliReader::Read( NxsToken &token) /* the token used to read from `in' */ { isEmpty = false; // This should be the semicolon after the block name // token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' after "; errormsg += id; errormsg += " block name, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } for (;;) { token.GetNextToken(); if (token.Abbreviation("ENdblock")) { HandleEndblock(token); break; } else if (token.Abbreviation("GarliReader")) { HandleGarliReader(token); } else if (token.Abbreviation("Help")) { HandleHelp(token); } else if (token.Abbreviation("Log")) { HandleLog(token); } else if (token.Abbreviation("EXecute")) { HandleExecute(token); } else if (token.Abbreviation("Show")) { HandleShow(token); } else if (token.Abbreviation("Quit")) { quit_now = true; message = "\nGarliReader says goodbye\n"; PrintMessage(); break; } else { SkippingCommand(token.GetToken()); do { token.GetNextToken(); } while (!token.AtEOF() && !token.Equals(";")); if (token.AtEOF()) { errormsg = "Unexpected end of file encountered"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } } }
/*---------------------------------------------------------------------------------------------------------------------- | Called when the HELP command needs to be parsed from within the GarliReader block. */ void GarliReader::HandleShow( NxsToken &token) /* the token used to read from `in' */ { // Retrieve all tokens for this command, stopping only in the event // of a semicolon or an unrecognized keyword // for (;;) { token.GetNextToken(); if (token.Equals(";")) break; else { errormsg = "Unexpected keyword ("; errormsg += token.GetToken(); errormsg += ") encountered reading HELP command"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } message = "\nNexus blocks currently stored:"; PrintMessage(); if (!taxa->IsEmpty()) { cerr << "\n TAXA block found" << endl; taxa->Report(cerr); if (logf_open) taxa->Report(logf); } if (!trees->IsEmpty()) { cerr << "\n TREES block found" << endl; trees->Report(cerr); if (logf_open) trees->Report(logf); } if (!assumptions->IsEmpty()) { cerr << "\n ASSUMPTIONS block found" << endl; assumptions->Report(cerr); if (logf_open) assumptions->Report(logf); } if (!distances->IsEmpty()) { cerr << "\n DISTANCES block found" << endl; distances->Report(cerr); if (logf_open) distances->Report(logf); } if (!characters->IsEmpty()) { cerr << "\n CHARACTERS block found" << endl; characters->Report(cerr); if (logf_open) characters->Report(logf); } if (!data->IsEmpty()) { cerr << "\n DATA block found" << endl; data->Report(cerr); if (logf_open) data->Report(logf); } }
/*---------------------------------------------------------------------------------------------------------------------- | Reads characters from in until a complete token has been read and stored in token. GetNextToken performs a number | of useful operations in the process of retrieving tokens: |~ | o any underscore characters encountered are stored as blank spaces (unless the labile flag bit preserveUnderscores | is set) | o if the first character of the next token is an isolated single quote, then the entire quoted NxsString is saved | as the next token | o paired single quotes are automatically converted to single quotes before being stored | o comments are handled automatically (normal comments are treated as whitespace and output comments are passed to | the function OutputComment which does nothing in the NxsToken class but can be overridden in a derived class to | handle these in an appropriate fashion) | o leading whitespace (including comments) is automatically skipped | o if the end of the file is reached on reading this token, the atEOF flag is set and may be queried using the AtEOF | member function | o punctuation characters are always returned as individual tokens (see the Maddison, Swofford, and Maddison paper | for the definition of punctuation characters) unless the flag ignorePunctuation is set in labileFlags, | in which case the normal punctuation symbols are treated just like any other darkspace character. |~ | The behavior of GetNextToken may be altered by using labile flags. For example, the labile flag saveCommandComments | can be set using the member function SetLabileFlagBit. This will cause comments of the form [&X] to be saved as | tokens (without the square brackets), but only for the aquisition of the next token. Labile flags are cleared after | each application. */ void NxsToken::GetNextToken() { ResetToken(); char ch = ' '; if (saved == '\0' || IsWhitespace(saved)) { // Skip leading whitespace // while( IsWhitespace(ch) && !atEOF) ch = GetNextChar(); saved = ch; } for(;;) { // Break now if singleCharacterToken mode on and token length > 0. // if (labileFlags & singleCharacterToken && token.size() > 0) break; // Get next character either from saved or from input stream. // if (saved != '\0') { ch = saved; saved = '\0'; } else ch = GetNextChar(); // Break now if we've hit EOF. // if (atEOF) break; if (ch == '\n' && labileFlags & newlineIsToken) { if (token.size() > 0) { // Newline came after token, save newline until next time when it will be // reported as a separate token. // atEOL = 0; saved = ch; } else { atEOL = 1; AppendToToken(ch); } break; } else if (IsWhitespace(ch)) { // Break only if we've begun adding to token (remember, if we hit a comment before a token, // there might be further white space between the comment and the next token). // if (token.size() > 0) break; } else if (ch == '_') { // If underscores are discovered in unquoted tokens, they should be // automatically converted to spaces. // if (!(labileFlags & preserveUnderscores)) ch = ' '; AppendToToken(ch); } else if (ch == '[') { // Get rest of comment and deal with it, but notice that we only break if the comment ends a token, // not if it starts one (comment counts as whitespace). In the case of command comments // (if saveCommandComment) GetComment will add to the token NxsString, causing us to break because // token.size() will be greater than 0. comment.clear(); GetComment(); if (token.size() > 0) break; } else if (ch == '(' && labileFlags & parentheticalToken) { AppendToToken(ch); // Get rest of parenthetical token. // GetParentheticalToken(); break; } else if (ch == '{' && labileFlags & curlyBracketedToken) { AppendToToken(ch); // Get rest of curly-bracketed token. // GetCurlyBracketedToken(); break; } else if (ch == '\"' && labileFlags & doubleQuotedToken) { // Get rest of double-quoted token. // GetDoubleQuotedToken(); break; } else if (ch == '\'') { if (token.size() > 0) { // We've encountered a single quote after a token has // already begun to be read; should be another tandem // single quote character immediately following. // ch = GetNextChar(); if (ch == '\'') AppendToToken(ch); else { errormsg = "Expecting second single quote character"; throw NxsException( errormsg, GetFilePosition(), GetFileLine(), GetFileColumn()); } } else { // Get rest of quoted NEXUS word and break, since // we will have eaten one token after calling GetQuoted. // GetQuoted(); } break; } else if (IsPunctuation(ch)) { if (token.size() > 0) { // If we've already begun reading the token, encountering // a punctuation character means we should stop, saving // the punctuation character for the next token. // saved = ch; break; } else { // If we haven't already begun reading the token, encountering // a punctuation character means we should stop and return // the punctuation character as this token (i.e., the token // is just the single punctuation character. // AppendToToken(ch); break; } } else { AppendToToken(ch); } } labileFlags = 0; }
/*---------------------------------------------------------------------------------------------------------------------- | This function provides the ability to read everything following the block name (which is read by the NxsReader | object) to the end or endblock statement. Characters are read from the input stream in. Overrides the abstract | virtual function in the base class. */ void NxsTaxaBlock::Read( NxsToken &token) /* the token used to read from in */ { ntax = 0; unsigned nominal_ntax = 0; isEmpty = false; isUserSupplied = true; DemandEndSemicolon(token, "BEGIN TAXA"); for (;;) { token.GetNextToken(); if (token.Equals("DIMENSIONS")) { // This should be the NTAX keyword // token.GetNextToken(); if (!token.Equals("NTAX")) { errormsg = "Expecting NTAX keyword, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } DemandEquals(token, "after NTAX"); nominal_ntax = DemandPositiveInt(token, "NTAX"); DemandEndSemicolon(token, "DIMENSIONS"); } // if (token.Equals("DIMENSIONS")) else if (token.Equals("TAXLABELS")) { if (nominal_ntax <= 0) { errormsg = "NTAX must be specified before TAXLABELS command"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } for (unsigned i = 0; i < nominal_ntax; i++) { token.GetNextToken(); //@pol should check to make sure this is not punctuation AddTaxonLabel(token.GetToken()); } DemandEndSemicolon(token, "TAXLABELS"); } // if (token.Equals("TAXLABELS")) else if (token.Equals("END") || token.Equals("ENDBLOCK")) { DemandEndSemicolon(token, "ENDBLOCK"); break; } // if (token.Equals("END") || token.Equals("ENDBLOCK")) else { SkippingCommand(token.GetToken()); do { token.GetNextToken(); } while (!token.AtEOF() && !token.Equals(";")); if (token.AtEOF()) { errormsg = "Unexpected end of file encountered"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } // token not END, ENDBLOCK, TAXLABELS, or DIMENSIONS } // GetNextToken loop }
/*---------------------------------------------------------------------------------------------------------------------- | This function provides the ability to read everything following the block name (which is read by the NxsReader | object) to the end or endblock statement. Characters are read from the input stream in. Overrides the abstract | virtual function in the base class. */ void NxsTaxaBlock::Read( NxsToken &token) /* the token used to read from in */ { ntax = 0; int nominal_ntax = 0; isEmpty = false; isUserSupplied = true; // This should be the semicolon after the block name // token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' after TAXA block name, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } for (;;) { token.GetNextToken(); if (token.Equals("DIMENSIONS")) { // This should be the NTAX keyword // token.GetNextToken(); if (!token.Equals("NTAX")) { errormsg = "Expecting NTAX keyword, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } // This should be the equals sign // token.GetNextToken(); if (!token.Equals("=")) { errormsg = "Expecting '=', but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } // This should be the number of taxa // token.GetNextToken(); nominal_ntax = atoi(token.GetToken().c_str()); if (nominal_ntax <= 0) { errormsg = "NTAX should be greater than zero ("; errormsg += token.GetToken(); errormsg += " was specified)"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } // This should be the terminating semicolon // token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' to terminate DIMENSIONS command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } // if (token.Equals("DIMENSIONS")) else if (token.Equals("TAXLABELS")) { if (nominal_ntax <= 0) { errormsg = "NTAX must be specified before TAXLABELS command"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } for (unsigned i = 0; (int)i < nominal_ntax; i++) { token.SetLabileFlagBit(NxsToken::hyphenNotPunctuation + NxsToken::preserveUnderscores); token.GetNextToken(); //@pol should check to make sure this is not punctuation AddTaxonLabel(token.GetToken()); } // This should be terminating semicolon // token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' to terminate TAXLABELS command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } // if (token.Equals("TAXLABELS")) else if (token.Equals("END") || token.Equals("ENDBLOCK")) { // Get the semicolon following END // token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' to terminate the ENDBLOCK command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } break; } // if (token.Equals("END") || token.Equals("ENDBLOCK")) else { SkippingCommand(token.GetToken()); do { token.GetNextToken(); } while (!token.AtEOF() && !token.Equals(";")); if (token.AtEOF()) { errormsg = "Unexpected end of file encountered"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } // token not END, ENDBLOCK, TAXLABELS, or DIMENSIONS } // GetNextToken loop }