/** * @method HandleDimensionsCommand [void:protected] * @param token [NexusToken&] the token used to read from in * @throws XNexus * * Called when DIMENSIONS command needs to be parsed from within the * DISTANCES block. Deals with everything after the token DIMENSIONS * up to and including the semicolon that terminates the DIMENSIONS * command. */ void DistancesBlock::HandleDimensionsCommand( NexusToken& token ) { for(;;) { token.GetNextToken(); // token should either be ';' or the name of a subcommand // if( token.Equals(";") ) { break; } else if( token.Equals("NEWTAXA") ) { ntax = 0; newtaxa = 1; } else if( token.Equals("NTAX") ) { if( !newtaxa ) { errormsg = "Must specify NEWTAXA before NTAX if new taxa are being defined"; throw XNexus( 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 XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } // this should be the number of taxa token.GetNextToken(); ntax = atoi( token.GetToken().c_str() ); } else if( token.Equals("NCHAR") ) { // this should be the equals sign token.GetNextToken(); if( !token.Equals("=") ) { errormsg = "Expecting '=' but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } // this should be the number of characters token.GetNextToken(); nchar = atoi( token.GetToken().c_str() ); } } if( ntax == 0 ) ntax = taxa.GetNumTaxonLabels(); }
/** * @method Read [void:protected] * @param token [NexusToken&] the token used to read from in * @throws XNexus * * This function provides the ability to read everything following * the block name (which is read by the Nexus 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 AssumptionsBlock::Read( NexusToken& token ) { 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 XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } for(;;) { token.GetNextToken(); if( token.Equals("EXSET") ) { HandleExset( token ); } else if( token.Equals("TAXSET") ) { HandleTaxset( token ); } else if( token.Equals("CHARSET") ) { HandleCharset( token ); } else 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 XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } } } }
/** * @method HandleMatrixCommand [void:protected] * @param token [NexusToken&] the token used to read from in * @throws XNexus * * Called when MATRIX command needs to be parsed from within the * DISTANCES block. Deals with everything after the token MATRIX * up to and including the semicolon that terminates the MATRIX * command. */ void DistancesBlock::HandleMatrixCommand( NexusToken& token ) { int i; if( ntax == 0 ) ntax = taxa.GetNumTaxonLabels(); if( ntax == 0 ) { errormsg = "MATRIX command cannot be read if NTAX is zero"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } if( triangle == both && !diagonal ) { errormsg = "Cannot specify NODIAGONAL and TRIANGLE=BOTH at the same time"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } if( newtaxa ) taxa.Reset(); // allocate memory to hold the taxonPos array // if( taxonPos != NULL ) delete [] taxonPos; taxonPos = new int[ntax]; for( i = 0; i < ntax; i++ ) taxonPos[i] = -1; // allocate memory to hold the matrix // if( matrix != NULL ) delete matrix; matrix = new DistanceDatum*[ntax]; for( i = 0; i < ntax; i++ ) matrix[i] = new DistanceDatum[ntax]; int offset = 0; int done = 0; while( !done ) { done = HandleNextPass( token, offset ); } // token should be equal to the terminating semicolon token.GetNextToken(); if( !token.Equals(";") ) { errormsg = "Expecting ';' to terminate MATRIX command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } }
/** * @method HandleTaxset [void:protected] * @param token [NexusToken&] the token used to read from in * @throws XNexus * * ? */ void AssumptionsBlock::HandleTaxset( NexusToken& token ) { bool asterisked = false; // Next token should be either an asterisk or the name of a taxset token.GetNextToken(); if( token.Equals("*") ) { asterisked = true; token.GetNextToken(); } // Token now stored should be the name of a taxset nxsstring taxset_name = token.GetToken(); // Now grab the equals sign token.GetNextToken(); if( !token.Equals("=") ) { errormsg = "Expecting '=' in TAXSET definition but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } IntSet s; int totalTaxa = taxa.GetNumTaxonLabels(); SetReader( token, totalTaxa, s, *this, SetReader::taxset ).Run(); taxsets[taxset_name] = s; if( asterisked ) def_taxset = taxset_name; }
/** * @method HandleCharset [void:protected] * @param token [NexusToken&] the token used to read from in * @throws XNexus * * Reads and stores information contained in the command * CHARSET within an ASSUMPTIONS block. */ void AssumptionsBlock::HandleCharset( NexusToken& token ) { bool asterisked = false; // Next token should be either an asterisk or the name of a charset token.GetNextToken(); if( token.Equals("*") ) { asterisked = true; token.GetNextToken(); } // Token now stored should be the name of a charset nxsstring charset_name = token.GetToken(); // Now grab the equals sign token.GetNextToken(); if( !token.Equals("=") ) { errormsg = "Expecting '=' in CHARSET definition but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } assert( charBlockPtr != NULL ); CharactersBlock& charBlock = *charBlockPtr; IntSet s; int totalChars = charBlock.GetNCharTotal(); SetReader( token, totalChars, s, charBlock, SetReader::charset ).Run(); charsets[charset_name] = s; if( asterisked ) def_charset = charset_name; }
/** * @method HandleEndblock [void:protected] * @param token [NexusToken&] the token used to read from in * @throws XNexus * * Called when the END or ENDBLOCK command needs to be parsed * from within the ASSUMPTIONS block. Basically just checks to make * sure the next token in the data file is a semicolon. */ void AssumptionsBlock::HandleEndblock( NexusToken& token ) { // 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 XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } }
/** * @method HandleTaxlabelsCommand [void:protected] * @param token [NexusToken&] the token used to read from in * @throws XNexus * * Called when TAXLABELS command needs to be parsed from within the * DISTANCES block. Deals with everything after the token TAXLABELS * up to and including the semicolon that terminates the TAXLABELS * command. */ void DistancesBlock::HandleTaxlabelsCommand( NexusToken& token ) { if( !newtaxa ) { errormsg = "NEWTAXA must have been specified in DIMENSIONS command to use the TAXLABELS command in a "; errormsg += id; errormsg += " block"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } if( ntax == 0 ) { errormsg = "NTAX must be specified before TAXLABELS command"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } for( int i = 0; i < ntax; i++ ) { token.GetNextToken(); taxa.AddTaxonLabel( token.GetToken() ); } token.GetNextToken(); // this should be terminating semicolon if( !token.Equals(";") ) { errormsg = "Expecting ';' to terminate TAXLABELS command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } // OPEN ISSUE: Some may object to setting newtaxa to 0 here, because then the // fact that new taxa were specified in this DISTANCES block rather than in // a preceding TAXA block is lost. This will only be important if we wish to // recreate the original data file, which I don't anticipate anyone doing with // this code (too difficult to remember all comments, the order of blocks in // the file, etc.) newtaxa = 0; }
/** * @method Read [void:protected] * @param token [NexusToken&] the token used to read from in * @throws XNexus * * This function provides the ability to read everything following the block name * (which is read by the Nexus 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 TaxaBlock::Read( NexusToken& token ) { isEmpty = false; token.GetNextToken(); // this should be the semicolon after the block name if( !token.Equals(";") ) { errormsg = "Expecting ';' after TAXA block name, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } for(;;) { token.GetNextToken(); if( token.Equals("DIMENSIONS") ) { token.GetNextToken(); // this should be the NTAX keyword if( !token.Equals("NTAX") ) { errormsg = "Expecting NTAX keyword, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } token.GetNextToken(); // this should be the equals sign if( !token.Equals("=") ) { errormsg = "Expecting '=', but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } token.GetNextToken(); // this should be the number of taxa ntax = atoi( token.GetToken().c_str() ); if( ntax <= 0 ) { errormsg = "NTAX should be greater than zero ("; errormsg += token.GetToken(); errormsg += " was specified)"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } token.GetNextToken(); // this should be the terminating semicolon if( !token.Equals(";") ) { errormsg = "Expecting ';' to terminate DIMENSIONS command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } } else if( token.Equals("TAXLABELS") ) { if( ntax <= 0 ) { errormsg = "NTAX must be specified before TAXLABELS command"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } for( int i = 0; i < ntax; i++ ) { token.GetNextToken(); taxonLabels.push_back( token.GetToken() ); } token.GetNextToken(); // this should be terminating semicolon if( !token.Equals(";") ) { errormsg = "Expecting ';' to terminate TAXLABELS command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } } else if( token.Equals("END") ) { // get the semicolon following END token.GetNextToken(); if( !token.Equals(";") ) { errormsg = "Expecting ';' to terminate the END command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } break; } else if( token.Equals("ENDBLOCK") ) { // get the semicolon following ENDBLOCK token.GetNextToken(); if( !token.Equals(";") ) { errormsg = "Expecting ';' to terminate the ENDBLOCK command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } break; } else { SkippingCommand( token.GetToken() ); do { token.GetNextToken(); } while( !token.AtEOF() && !token.Equals(";") ); if( token.AtEOF() ) { errormsg = "Unexpected end of file encountered"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } } } }
/** * @method Execute [void:public] * @param token [NexusToken&] the token object used to grab Nexus tokens * @param notifyStartStop [bool] if true, ExecuteStarting and ExecuteStopping will be called (true by default) * * Reads the Nexus data file from the input stream provided by token. This function * is responsible for reading through the name of a each block. Once * it has read a block name, it searches blockList for a block object * to handle reading the remainder of the block's contents. The block * object is responsible for reading the end or endblock command as well * as the trailing semicolon. This function also handles reading * comments that are outside of blocks, as well as the initial #NEXUS * keyword. The notifyStartStop argument is provided in case you do not * wish the ExecuteStart and ExecuteStop functions to be called. These functions * are primarily used for creating and destroying a dialog box to show progress, * and nested Execute calls can thus cause problems (e.g., a dialog box is * destroyed when the inner Execute calls ExecuteStop and the outer Execute * still expects the dialog box to be available). Specifying notifyStartStop * false for all the nested Execute calls thus allows the outermost Execute call * to control creation and destruction of the dialog box. */ void Nexus::Execute( NexusToken& token, bool notifyStartStop /* = true */ ) { char id_str[256]; bool disabledBlock = false; nxsstring errormsg; try { token.GetNextToken(); } catch( XNexus x ) { NexusError( token.errormsg, 0, 0, 0 ); return; } if( !token.Equals("#NEXUS") ) { errormsg = "Expecting #NEXUS to be the first token in the file, but found "; errormsg += token.GetToken(); errormsg += " instead"; NexusError( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); return; } if( notifyStartStop ) ExecuteStarting(); for(;;) { token.SetLabileFlagBit( NexusToken::saveCommandComments ); token.GetNextToken(); if( token.AtEOF() ) break; if( token.Equals("BEGIN") ) { disabledBlock = false; token.GetNextToken(); NexusBlock* curr; for( curr = blockList; curr != NULL; curr = curr->next ) { if( !token.Equals( curr->GetID() ) ) continue; if( !curr->IsEnabled() ) { disabledBlock = true; SkippingDisabledBlock( token.GetToken() ); continue; } strcpy( id_str, curr->GetID().c_str() ); EnteringBlock( id_str /*curr->GetID()*/ ); curr->Reset(); try { curr->Read( token ); } catch( XNexus x ) { NexusError( curr->errormsg, x.pos, x.line, x.col ); curr->Reset(); return; } ExitingBlock( id_str /*curr->GetID()*/ ); break; } if( curr == NULL ) { token.BlanksToUnderscores(); nxsstring currBlock = token.GetToken(); if( !disabledBlock ) SkippingBlock( currBlock ); for(;;) { token.GetNextToken(); if( token.Equals("END") || token.Equals("ENDBLOCK") ) { token.GetNextToken(); if( !token.Equals(";") ) { errormsg = "Expecting ';' after END or ENDBLOCK command, but found "; errormsg += token.GetToken(); errormsg += " instead"; NexusError( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); return; } break; } if( token.AtEOF() ) { errormsg = "Encountered end of file before END or ENDBLOCK in block "; errormsg += currBlock; NexusError( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); return; } } } // if token not found amongst known block IDs } // if token equals BEGIN else if( token.Equals("&SHOWALL") ) { NexusBlock* curr; for( curr = blockList; curr != NULL; curr = curr->next ) { DebugReportBlock(*curr); } } else if( token.Equals("&LEAVE") ) { break; } } // for(;;) if( notifyStartStop ) ExecuteStopping(); }
void MyCharactersBlock::HandleMatrix (NexusToken& token) { int i, j; if (ntax == 0) { errormsg = "Must precede "; errormsg += id; errormsg += " block with a TAXA block or specify NEWTAXA and NTAX in the DIMENSIONS command"; throw XNexus (errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } if (ntaxTotal == 0) ntaxTotal = taxa.GetNumTaxonLabels(); // We use >= rather than just > below because someone might have // ELIMINATEd all characters, and we should allow that (even though it // is absurd) assert (nchar >= 0); if (matrix != NULL) delete matrix; mContData.clear(); if (GetDataType() != continuous) { matrix = new DiscreteMatrix (ntax, nchar); } // Allocate memory for (and initialize) the arrays activeTaxon and // activeChar. // All characters and all taxa are initially active. activeTaxon = new bool[ntax]; for (i = 0; i < ntax; i++) activeTaxon[i] = true; activeChar = new bool[nchar]; for (j = 0; j < nchar; j++) activeChar[j] = true; // The value of ncharTotal is normally identical to the value of nchar // specified in the CHARACTERS block DIMENSIONS command. If an // ELIMINATE command is processed, however, nchar < ncharTotal. Note // that the ELIMINATE command will have already been read by now, and // the ELIMINATEd character numbers will be stored in the IntSet // eliminated. // // Note that if an ELIMINATE command has been read, charPos will have // already been created; thus, we only need to allocate and initialize // charPos if user did not specify an ELIMINATE command if (charPos == NULL) BuildCharPosArray(); // The value of ntaxTotal equals the number of taxa specified in the // TAXA block, whereas ntax equals the number of taxa specified in // the DIMENSIONS command of the CHARACTERS block. These two numbers // will be identical unless some taxa were left out of the MATRIX // command of the CHARACTERS block, in which case ntax < ntaxTotal. if (taxonPos != NULL) delete [] taxonPos; taxonPos = new int[ntaxTotal]; for (i = 0; i < ntaxTotal; i++) taxonPos[i] = -1; if (GetDataType() == continuous) handleContMatrix (token); else if (transposing) HandleTransposedMatrix (token); else HandleStdMatrix (token); // If we've gotten this far, presumably it is safe to // tell the ASSUMPTIONS block that were ready to take on // the responsibility of being the current character-containing // block (to be consulted if characters are excluded or included // or if taxa are deleted or restored) assumptionsBlock.SetCallback(this); // this should be the terminating semicolon at the end of the matrix command if (GetDataType() != continuous) token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' at the end of the MATRIX command; found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus (errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } }
/** * @method Read [void:protected] * @param token [NexusToken&] the token used to read from in * @throws XNexus * * This function provides the ability to read everything following the block name * (which is read by the Nexus 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 DistancesBlock::Read( NexusToken& token ) { isEmpty = false; token.GetNextToken(); // this should be the semicolon after the block name if( !token.Equals(";") ) { errormsg = "Expecting ';' after "; errormsg += id; errormsg += " block name, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } for(;;) { token.GetNextToken(); if( token.Equals("DIMENSIONS") ) { HandleDimensionsCommand( token ); } else if( token.Equals("FORMAT") ) { HandleFormatCommand( token ); } else if( token.Equals("TAXLABELS") ) { HandleTaxlabelsCommand( token ); } else if( token.Equals("MATRIX") ) { HandleMatrixCommand( token ); } else if( token.Equals("END") ) { // get the semicolon following END token.GetNextToken(); if( !token.Equals(";") ) { errormsg = "Expecting ';' to terminate the END command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } break; } else if( token.Equals("ENDBLOCK") ) { // get the semicolon following ENDBLOCK token.GetNextToken(); if( !token.Equals(";") ) { errormsg = "Expecting ';' to terminate the ENDBLOCK command, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } break; } else { SkippingCommand( token.GetToken() ); do { token.GetNextToken(); } while( !token.AtEOF() && !token.Equals(";") ); if( token.AtEOF() ) { errormsg = "Unexpected end of file encountered"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } } } }
/** * @method HandleNextPass [int:protected] * @param token [NexusToken&] the token we are using for reading the data file * @param offset [int&] the offset (see below) * * Called from within HandleMatrix, this function is used to deal with interleaved * matrices. It is called once for each pass through the taxa. * * <P>The local variable jmax records the number of columns read in the current * interleaved page and is used to determine the offset used for j in subsequent * pages. */ int DistancesBlock::HandleNextPass( NexusToken& token, int& offset ) { int i, j, k, jmax = 0, done = 0; int i_first = 0; if( triangle == lower ) i_first = offset; int i_last = ntax; for( i = i_first; i < i_last; i++ ) { // Deal with taxon label if provided // if( labels && ( !newtaxa || offset>0 ) ) { do { token.SetLabileFlagBit( NexusToken::newlineIsToken ); token.GetNextToken(); } while( token.AtEOL() ); try { k = taxa.FindTaxon( token.GetToken() ); if( taxonPos[i]==-1 ) taxonPos[i] = k; else if( taxonPos[i] != k ) { errormsg = "Taxon labeled "; errormsg += token.GetToken(); errormsg += " is out of order compared to previous interleave pages"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } } catch (std::out_of_range) { errormsg = "Could not find "; errormsg += token.GetToken(); errormsg += " among taxa previously defined"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } } else if( labels && newtaxa ) { do { token.SetLabileFlagBit( NexusToken::newlineIsToken ); token.GetNextToken(); } while( token.AtEOL() ); taxa.AddTaxonLabel( token.GetToken() ); taxonPos[i] = i; } // Now deal with the row of distance values // int true_j = 0; for( j = 0; j < ntax; j++ ) { if( i == ntax-1 && j == ntax-1 ) { done = 1; } if( i == ntax-1 && true_j == ntax-1 ) { done = 1; break; } if( i == ntax-1 && !diagonal && triangle==upper ) { done = 1; break; } if( !diagonal && triangle==lower && j == ntax-offset-1) { done = 1; break; } token.SetLabileFlagBit( NexusToken::newlineIsToken ); token.GetNextToken(); if( token.AtEOL() ) { if( j > jmax ) { jmax = j; if( !diagonal && triangle == upper && i >= offset ) jmax++; if( interleave && triangle == upper ) i_last = jmax + offset; } break; } true_j = j+offset; if( triangle==upper && i > offset ) true_j += ( i - offset ); if( !diagonal && triangle==upper && i >= offset ) true_j++; if( true_j == ntax ) { errormsg = "Too many distances specified in row just read in"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } std::string t = token.GetToken(); if( token.GetTokenLength() == 1 && t[0] == missing ) SetMissing( i, true_j ); else SetDistance( i, true_j, atof( t.c_str() ) ); } } offset += jmax; if( done ) return 1; else return 0; }
/** * @method HandleFormatCommand [void:protected] * @param token [NexusToken&] the token used to read from in * @throws XNexus * * Called when FORMAT command needs to be parsed from within the * DISTANCES block. Deals with everything after the token FORMAT * up to and including the semicolon that terminates the FORMAT * command. */ void DistancesBlock::HandleFormatCommand( NexusToken& token ) { for(;;) { token.GetNextToken(); // token should either be ';' or the name of a subcommand // if( token.Equals(";") ) { break; } else if( token.Equals("TRIANGLE") ) { // this should be the equals sign token.GetNextToken(); if( !token.Equals("=") ) { errormsg = "Expecting '=' but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } // this should be LOWER, UPPER, or BOTH token.GetNextToken(); if( token.Equals("LOWER") ) triangle = lower; else if( token.Equals("UPPER") ) triangle = upper; else if( token.Equals("BOTH") ) triangle = both; else { errormsg = "Expecting UPPER, LOWER, or BOTH but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } } else if( token.Equals("DIAGONAL") ) { diagonal = 1; } else if( token.Equals("NODIAGONAL") ) { diagonal = 0; } else if( token.Equals("LABELS") ) { labels = 1; } else if( token.Equals("NOLABELS") ) { labels = 0; } else if( token.Equals("INTERLEAVE") ) { interleave = 1; } else if( token.Equals("NOINTERLEAVE") ) { interleave = 0; } else if( token.Equals("MISSING") ) { // this should be the equals sign token.GetNextToken(); if( !token.Equals("=") ) { errormsg = "Expecting '=' but found "; errormsg += token.GetToken(); errormsg += " instead"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } // this should be the missing data symbol token.GetNextToken(); if( token.GetTokenLength() != 1 ) { errormsg = "Missing data symbol specified ("; errormsg += token.GetToken(); errormsg += ") is invalid (must be a single character)"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } missing = token.GetToken()[0]; } else { errormsg = "Token specified ("; errormsg += token.GetToken(); errormsg += ") is an invalid subcommand for the FORMAT command"; throw XNexus( errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn() ); } } }