Beispiel #1
0
void LabelRange()
{
  /*
    LabelRange -> label [ .. label ]
  */

  if ( debugMode) printf( "In LabelRange\n");
  if ( isLabel( sym))
  {
    writesym();
    nextsym();
  }
  else 
  {
    error( invalid_sym, 1);
    return;
  }

  if ( sym == doubledot)
  {
    if ( isLabel( sym))
    {
      writesym();
      nextsym();
    }
    else 
    {
      error( invalid_sym, 1);
      return;
    } 
  }
  if ( debugMode) printf( "Out LabelRange\n");
}
Beispiel #2
0
/**
 * This function returns the next line on file.
 * fp - the file.
 * ln - empty array , will contain the line.
 * stepOneEnd - boolean pointer. (is EOF?)
 */
void getLine(FILE* fp, line ln[], bool* stepOneEnd)
{
	string startline = malloc(sizeof(char) * maxLineLength);
	int idx = 0, i = 1;
	fgets(startline, maxLineLength, fp);
	while(idx < strlen(startline) && i < lineVar){
		readNextWord(startline, &idx, stepOneEnd, (ln + i));
		if(strcmp(ln[i].word, "EMPTY") == 0)
			break;
		if(i == 1 && isLabel(ln[i])){
			ln[i].word[idx - 2] = (char)'\0';
			i--;
			ln[i].word = malloc(sizeof(string) * 100);
			strcpy(ln[i].word, ln[i + 1].word);
			ln[i].wordIdx = ln[i + 1].wordIdx;
			free(ln[i + 1].word);
			ln[i + 1].word = "NULL";
		}
		if(strcmp(ln[i].word, ".data") == 0){
			ln[i].wordIdx = handleData(idx, startline, stepOneEnd);
			break;
		}
		if(idx < strlen(startline))
			ln[i + 1].wordIdx = ln[i].wordIdx;
		i++;
	}
	free(startline);
}
Beispiel #3
0
Token TokenCreator::identifyTokenType(Token token, assembly_language language) {
	std::string type;
	this->language = language;
	if (isLabel(token))
		type = "LABEL";
	else if (isInstruction(token))
		type = "INSTRUCTION";
	else if(isDirective(token))
		type = "DIRECTIVE";
	else
		type = "OPERAND";
	return Token(token.name, token.line_number, type);
}
size_t parse1::insert(const string & str){
	string t_str = remove_white( remove_comments(str));
	if (isLabel(t_str)) {
		makeSymbol(t_str);
		return linked_list.size();
	}else if(is_at(t_str)){
		makeSplit(t_str);
		return linked_list.size();
	}
	if (t_str == "") { return linked_list.size();}
	else {linked_list.push_back(t_str);}
	return linked_list.size();
}
inputType identifyType (char input[]) {

    if (isDirective(input)) {

        return DIRECTIVE;
    } else if (isLabel(input)) {
        return LABEL;
    } else if (isComment(input)) {
        return COMMENT;
    } else  if(isInstruction(input)) {
        return INSTRUCTION;
    }

    return ERROR;

}
Beispiel #6
0
void Case() // uppercase 'Case' since 'case' is reserved in C
{
  /*
    case -> [ CaseLabList : StatSeq ]
  */

  if ( debugMode) printf( "In Case\n");
  // first of CaseLabList is first of LabelRange, which is first of label
  if ( isLabel( sym))  // then, this is ostensibly not a null rule
  {
    CaseLabList();
    accept( colon, 153);
    StatSeq();
  }
  if ( debugMode) printf( "Out Case\n");
}
// calculates the limit you can execute to
word_t calculateExecuteLimit(References* r)
{
    word_t limit = 0x0;
    int i = 0;

    for (i = 0; i < r->currentI; i++)
    {
        if (r->entries[i]->resolved)
        {
            if (!isLabel(r->entries[i]->instruction))
            {
                limit = r->entries[i]->address;
            } else if (r->currentAddress > 0)
            {
                limit = r->entries[i]->address - 4;
            }
        } else
        {
            return limit;
        }
    }
    return limit;
}
bool QwtPBPaintFilter::cmd(int c, QPainter *painter, QPDevCmdParam *param)
{
    switch(c)
    {
        case PdcDrawTextFormatted:
        case PdcDrawText2Formatted:
        {
            Qt::TextFormat textFormat = d_button->usedTextFormat();
            if ( textFormat == Qt::PlainText )
            {
                param[1].ival = d_button->alignment();

                QRect &r = *((QRect *)param[0].rect);
                r = indentRect(r);

                return QPicture::cmd(c, painter, param);
            }
            if ( textFormat == Qt::RichText )
            {
                if ( !d_inFilter ) // avoid recursive calls
                {
                    d_inFilter = TRUE;
                    QwtRichText richText(*param[2].str, painter->font(), 
                        d_button->alignment(), painter->pen().color());
                    richText.draw(painter, indentRect(*param[0].rect));
                    d_inFilter = FALSE;
                    return TRUE;
                }
            }
            break;
        }
        case PdcDrawPixmap:
        {
            if ( d_inFilter ) // avoid recursive calls
            {
                // There might be pixmaps embedded in rich text.
                // This problem is solved by the d_inFilter guard 
                // above too.
                break;
            }

            if ( isLabel(param[1].pixmap) &&
                !(d_button->alignment() & Qt::AlignCenter))
            {
                const QRect contentsRect =
#if QT_VERSION >= 300
                    d_button->style().subRect( 
                        QStyle::SR_PushButtonContents, d_button);
#else
                    d_button->style().pushButtonContentsRect(
                        (QPushButton *)d_button);
#endif

                QRect pixRect = contentsRect;
                if ( !d_iconRect.isEmpty() )
                    pixRect.setX(d_iconRect.right());

                // Many styles move the label right/down
                // when the button is down.

#if QT_VERSION >= 300
                const QRect &r = *((QRect *)param[0].rect);
#else
                const QRect r(*param[0].point, param[1].pixmap->size());
#endif
                const int offsetY = r.center().y() - pixRect.center().y();
                const int offsetX = d_iconRect.isEmpty() ? offsetY : 0;
                pixRect.moveBy(offsetX, offsetY);

                if ( d_button->indent() > 0 )
                {
                    const int indent = d_button->indent();
                    const int align = d_button->alignment();

                    if ( align & Qt::AlignRight )
                        pixRect.setRight(pixRect.right() - indent);
                    else if ( align & Qt::AlignLeft )
                        pixRect.setLeft(pixRect.left() + indent);

                    if ( align & Qt::AlignTop )
                        pixRect.setTop(pixRect.top() + indent);
                    else if ( align & Qt::AlignBottom )
                        pixRect.setBottom(pixRect.bottom() - indent);
                }

                pixRect &= contentsRect; // clip to contentsRect

                d_inFilter = TRUE;

                d_button->style().drawItem(painter, 
#if QT_VERSION >= 300
                    pixRect,
#else
                    pixRect.x(), pixRect.y(), 
                    pixRect.width(), pixRect.height(),
#endif
                    d_button->alignment(), d_button->colorGroup(), 
                    d_button->isEnabled(), param[1].pixmap, QString::null);

                d_inFilter = FALSE;
                return TRUE;
            }
            else
            {
                // We save the position of the icon. We need it later
                // to align the label pixmap. Hope that there are no styles
                // that paint the pixmap before the icon.
#if QT_VERSION < 300
                d_iconRect = QRect(*param[0].point, param[1].pixmap->size());
#else
                d_iconRect = *param[0].rect;
#endif
            }
            break;
        }
    }
    return QPicture::cmd(c, painter, param);
}
Beispiel #9
0
int
stm8instructionSize(const lineNode *pl)
{
  char *operand;
  char *op1start;
  char *op2start;
  int i = 0;
  operand = nextToken(pl->line);
  op1start = nextToken(NULL);
  op2start = nextToken(NULL);
  //fprintf(stderr, "op1start=%s op2start=%s\n", op1start, op2start);
  while(op2start && isspace(*op2start)) op2start++;
  //printf("operand=%s op1start=%s op2start=%s\n", operand, op1start, op2start);

  /* arity=1 */
  if(EQUALS(operand, "clr")
                || EQUALS(operand, "dec")
                || EQUALS(operand, "inc")
                || EQUALS(operand, "push")
                || EQUALS(operand, "swap")
                || EQUALS(operand, "jp")
                || EQUALS(operand, "cpl")
                || EQUALS(operand, "tnz"))
  {
    if(!op1start)
      return(3);
    if(op1start[0] == 'a' || op1start[1] == 'x')
      return(1);
    if(op1start[1] == 'y')
      return(2);
    if(op1start[0] == '(')
      op1start++;
    if(strstr(op1start, ",y)"))
      i++; // costs extra byte for operating with y
    if(isLabel(op1start))
      return(3);
    if(readint(op1start) <= 0xFF)
      return(2+i);
    /* op1 > 0xFF */
    if(EQUALS(operand, "jp") && !strchr(op1start, 'y'))
      return(3);
    return(4);
  }
  if(EQUALS(operand, "exg"))
  {
    if(isReg(op2start))
      return(1);
    else
      return(3);
  }
  if(EQUALS(operand, "addw") || EQUALS(operand, "subw"))
  {
    if(isImmediate(op2start) && op1start[0] == 'y')
      return(4);
    if(isImmediate(op2start))
      return(3);
    if(isSpIndexed(op2start))
      return(3);
    if(isLongoff(op2start, "x"))
      return(4);
  }
  if(EQUALS(operand, "cplw"))
  {
    if(op1start[0] == 'y')
      return(2);
    else
      return(1);
  }
  if(EQUALS(operand, "ldf"))
  {
    if(isRelativeAddr(op1start, "y") || isRelativeAddr(op2start, "y"))
      return(5);
    else
      return(4);
  }
  /* Operations that costs 2 or 3 bytes for immediate */
  if(ISINST(operand, "ld")
                || EQUALS(operand, "cp")
                || EQUALS(operand, "cpw")
                || ISINST(operand, "adc")
                || EQUALS(operand, "add")
                || ISINST(operand, "and")
                || ISINST(operand, "bcp")
                || ISINST(operand, "call")
                || ISINST(operand, "callr")
                || ISINST(operand, "jr")
                || ISINST(operand, "or")
                || ISINST(operand, "sbc")
                || EQUALS(operand, "sub")
                || ISINST(operand, "xor"))
  {
    char suffix;

    if(!op1start || !op2start)
      return(4);
    suffix = operand[strlen(operand)-1];
    if(suffix == 'w' && isImmediate(op2start))
      i++; // costs extra byte
    if(isSpIndexed(op1start) || isSpIndexed(op2start))
      return(2);
    if(!strcmp(op1start, "(x)") || !strcmp(op2start, "(x)"))
      return(1);
    if(!strcmp(op1start, "(y)") || !strcmp(op2start, "(y)"))
      return(2);
    if(isLabel(op1start) || isLabel(op2start))
      return(3+i);
    if(isShortoff(op1start, "x") || isShortoff(op2start, "x"))
      return(2);
    if(isShortoff(op1start, "y") || isShortoff(op2start, "y"))
      return(3);
    if(isLongoff(op1start, "x") || isLongoff(op2start, "x"))
      return(3);
    if(isRelativeAddr(op1start, "y"))
      return(4);
    if(strchr(op1start, 'y') || (strchr(op2start, 'y') && !EQUALS(operand, "ldw")))
      i++; // costs extra byte for operating with y
    if(isReg(op1start) && isReg(op2start))
      return(1+i);
    if(op2start[0] == '#')
      return(2+i); // ld reg, #immd
    if(readint(op2start) <= 0xFF)
      return(2+i);
    return(3+i);
  }

  /* mov costs 3, 4 or 5 bytes depending on it's addressing mode */
  if(EQUALS(operand, "mov")) {
    if(op2start && op2start[0] == '#')
      return(4);
    if(op2start && isLabel(op2start))
      return(5);
    if(op2start && readint(op2start) <= 0xFF)
      return(3);
    if(op2start && readint(op2start) > 0xFF)
      return(5);
  }

  /* Operations that always costs 1 byte */
  if(EQUALS(operand, "ccf")
                || EQUALS(operand, "divw")
                || EQUALS(operand, "exgw")
                || EQUALS(operand, "iret")
                || EQUALS(operand, "nop")
                || EQUALS(operand, "rcf")
                || EQUALS(operand, "ret")
                || EQUALS(operand, "retf")
                || EQUALS(operand, "rvf")
                || EQUALS(operand, "scf"))
  {
    return(1);
  }
  /* Operations that costs 2 or 1 bytes depending on 
     is the Y or X register used */
  if(EQUALS(operand, "clrw")
                || EQUALS(operand, "decw")
                || EQUALS(operand, "div")
                || EQUALS(operand, "incw")
                || EQUALS(operand, "mul")
                || EQUALS(operand, "negw")
                || EQUALS(operand, "popw")
                || EQUALS(operand, "pushw")
                || EQUALS(operand, "rlcw")
                || EQUALS(operand, "rlwa")
                || EQUALS(operand, "rrcw")
                || EQUALS(operand, "rrwa")
                || EQUALS(operand, "sllw")
                || EQUALS(operand, "slaw")
                || EQUALS(operand, "sraw")
                || EQUALS(operand, "srlw")
                || EQUALS(operand, "swapw")
                || EQUALS(operand, "tnzw"))
  {
    if((op1start && !strcmp(op1start, "y")) || (op2start && !strcmp(op2start, "y")))
      return(2);
    else
      return(1);
  }
  return(4);
}
Beispiel #10
0
void ParseInstructions(const std::string& in)
{
	boost::char_separator<char> delim(", ()");
	typedef boost::tokenizer< boost::char_separator< char > > tokenizer;

	size_t lineNum = 0;
	std::string bin;
	std::string rs;
	std::string rd;
	std::string rt;
	std::string imm;
	std::ifstream ifs(in);

	std::vector<std::string> sourceCode;
	std::map<size_t, std::bitset<32>> instructions;

	/* reads data from file */
	do
	{
		std::string line;
		std::ws(ifs);
		std::getline(ifs, line);
		sourceCode.push_back(line);
	} while (ifs.eof() == 0);

	std::vector<size_t> lineNums;
	std::map<std::string, size_t> labels;

	ParseLabels(sourceCode, labels);

	for (size_t i = 0; i < sourceCode.size(); ++i)
	{
		std::string s = sourceCode[i];
		
		if (!isLabel(s, labels))
		{
			tokenizer tokens(s, delim);
			tokenizer::iterator iter = tokens.begin();

			if (iter != tokens.end())
			{

				if (*iter == "syscall") // syscall
				{
					std::bitset<32> b(std::string("1100"));
					instructions.emplace(lineNum, b);
					++lineNum;
				}
				else if (s[0] == 'j') // jump
				{
			        bin = "000010";

					++iter;
					bin += GetAddress(*iter, labels);

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				}
				else if (*iter == "addiu") // addiu
				{
					
					bin = "001001";

					rt = *(++iter);
					rs = *(++iter);
					imm = *(++iter); 

					bin += GetReg(rs);
					bin += GetReg(rt);

					std::bitset<16> j(std::stoi(imm));
					
					bin += j.to_string();

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end addiu
				else if (*iter == "addu") // addu
				{
					bin = "000000";

					rd = *(++iter);
					rs = *(++iter);
					rt = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += GetReg(rd);

					bin += "00000";
					bin += "100001";

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				}
				else if (*iter == "and") // and
				{
					bin = "000000";

					rd = *(++iter);
					rs = *(++iter);
					rt = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += GetReg(rd);

					bin += "00000";
					bin += "100100";

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				}
				else if (*iter == "beq")
				{
					bin = "000100";

					rs = *(++iter);
					rt = *(++iter);
					imm = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += GetBranch(lineNum, imm, labels);

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end beq
				else if (*iter == "bne")
				{
					bin = "000101";

					rs = *(++iter);
					rt = *(++iter);
					imm = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += GetBranch(lineNum, imm, labels);

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end bne
				else if (*iter == "div") // div
				{
					bin = "000000";

					rs = *(++iter);
					rt = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += "0000000000";
					bin += "011010";

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end div
				else if (*iter == "lw") // lw
				{
					bin = "100011";

					rt = *(++iter);
					imm = *(++iter);
					rs = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += GetOffset(imm, labels);

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end lw
				else if (*iter == "mfhi") // mfhi
				{
					bin = "0000000000000000";

					rd = *(++iter);

					bin += GetReg(rd);
					bin += "00000010000";

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end mfhi
				else if (*iter == "mflo") // mflo
				{
					bin = "0000000000000000";

					rd = *(++iter);

					bin += GetReg(rd);
					bin += "00000010010";

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end mflo
				else if (*iter == "mult") // mult
				{
					bin = "000000";

					rs = *(++iter);
					rt = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += "0000000000011000";

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end mult
				else if (*iter == "or") // or
				{
					bin = "000000";

					rd = *(++iter);
					rs = *(++iter);
					rt = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += GetReg(rd);
					bin += "00000100101";

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end or
				else if (*iter == "slt") // slt
				{
					bin = "000000";

					rd = *(++iter);
					rs = *(++iter);
					rt = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += GetReg(rd);
					bin += "00000101010";

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end slt
				else if (*iter == "subu") // subu
				{
					bin = "000000";

					rd = *(++iter);
					rs = *(++iter);
					rt = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += GetReg(rd);
					bin += "00000100011";

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end subu
				else if (*iter == "sw") //sw
				{
					bin = "101011";

					rt = *(++iter);
					imm = *(++iter);
					rs = *(++iter);

					bin += GetReg(rs);
					bin += GetReg(rt);
					bin += GetOffset(imm, labels);

					std::bitset<32> b(bin);
					instructions.emplace(lineNum, b);
					++lineNum;
				} // end sw
				else
				{
					std::cout << "Error! Bad instruction on line " << lineNum << '\n';
					++lineNum;
				}
			} // end if
		} //end if
	} // end
	
	AddData(instructions, labels, sourceCode);

	Display(instructions);

	ifs.close();
} // end ParseInstructions
Beispiel #11
0
void AddData(std::map<size_t, std::bitset<32>>& instructions, std::map<std::string, size_t>& labels
	, const std::vector<std::string>& src)
{
	 typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
	 boost::char_separator<char> delim(": ,");

	 std::map<std::string, size_t>::iterator it = labels.find(".data");
	 size_t dataLoc = it->second; // i = is where .data is stored
	 bool DATA = false; // gets set to true when .data is read in, needed to avoid dereferencing bad token
	
	 size_t lineNum = instructions.size() + 1;
	 
	for (size_t i = 0; i < src.size(); ++i)
	{
		tokenizer token(src[i], delim);
		tokenizer::iterator iter = token.begin();

		while (iter != token.end())
		{
			if (*iter == ".data")
			{
				DATA = true;
			}
			else if (*iter == ".text")
			{

			}
			else if (!isLabel(*iter, labels))
			{
				if (*iter == ".word")
				{
					++iter;
	
					for (; iter != token.end(); ++iter)
					{
						std::bitset<32> b(std::stoi(*iter));
						instructions.emplace(lineNum, b);
						++lineNum;
					}
				}
				else if (*iter == ".space")
				{
					int numBytes = std::stoi(*(++iter));
					for (int i = 0; i < numBytes; ++i)
					{
						std::bitset<32> b;
						instructions.emplace(lineNum, b);
						++lineNum;
					}
				}
				else if (DATA)
				{
					std::bitset<32> b(std::stoi(*iter));
					instructions.emplace(lineNum, b);
					++lineNum;
				}
			} // end else if;
			else if (isLabel(*iter, labels))
			{	
				std::string tmp = *iter;
				tmp.pop_back(); // get rid of colon so it can be found
				std::map<std::string, size_t>::iterator loc = labels.find(tmp);
				
				std::map<std::string, size_t>::const_iterator ic = labels.find(*iter);

				if (ic->second >= dataLoc) // checks whether the label is in the .data segment, dangerous if .data comes before .text
				{
					++iter;
					if (*iter == ".word")
					{
						++iter;
					
						if (iter != token.end())
						{
							std::bitset<32> b(std::stoi(*iter));
							instructions.emplace(lineNum, b);
							++lineNum;
						}
					}
					else if (*iter == ".space")
					{
						int numBytes = std::stoi(*(++iter));

						for (int i = 0; i < numBytes; ++i)
						{
							std::bitset<32> b;
							instructions.emplace(lineNum, b);	
							++lineNum;
						}
					}
				}
			}
			++iter;
		} // end while
	} // end for
} //end AddData
Beispiel #12
0
void ParseLabels(std::vector<std::string>& src, std::map<std::string, size_t>& labels)
{
	size_t numLabels = 0;
	size_t dataLn = 0; // line number that .data is located on
	
	typedef boost::tokenizer < boost::char_separator< char > > tokenizer;
	boost::char_separator<char> delim(": ,");

	bool DATA = false;
	size_t distData = 0; // offset from Data or $gp

	for (size_t i = 0; i < src.size(); ++i)
	{
		std::string s = src[i];
		
		if (isLabel(s, labels))
		{
			tokenizer token(s, delim);
			tokenizer::iterator iter = token.begin();

			if (*iter == ".text")
			{
				
			}
			else if (DATA)
			{
				if (iter != token.end())
				{
					labels.emplace(*iter, (dataLn + distData));
					++iter;

					if (*iter == ".word")
					{
						++iter;

						for (; iter != token.end(); ++iter)
						{
							distData += 4;
						}
					}
					else if (*iter == ".space")
					{
						++iter;
						int stop = std::stoi(*iter);

						for (int i = 0; i < stop; ++i)
						{
							distData += 4;
						}
					}
				}
			}
			else
			{
				if (*iter == ".data")
				{
					DATA = true;
					dataLn = ((i - numLabels) - 1);
				}
				labels.emplace(*iter, ((i - numLabels) - 1)); // the - 1 accounts for counting from line 0, ensures the correct line is pointed to 
				++numLabels;
			}
		} // end if
	} // end for
} // end ParseLabels      
Beispiel #13
0
bool Line::isValid() const {
  return isInstruction() || isLabel() || isAlign() || isByte();
}
Beispiel #14
0
uint32_t Line::getLabel() const {
  assert(isLabel());
  return label;
}
Beispiel #15
0
AlnusNewickParser::Operator
AlnusNewickParser::scan()
{
INIT:
    reset();
    
    if (mCharacter == ' ') {
        ignore();
    }
    
    if (mOperator == Operator::COLON) {
        read();
        goto LEADING_DIGIT;
    }
    //    if (mOperator == Operator::QUOTATION_MARK) {
    //        read();
    //        goto ALPHABET;
    //    }
    
    if (mCharacter == '\'') {
        goto ALPHABET_WITH_QUOTATION_MARK;
    }
    
    if (isLabel(mCharacter)) {
        read();
        goto ALPHABET;
    }
    
    //    if (isnumber(mCharacter)) {
    //        read();
    //        goto LEADING_DIGIT;
    //    }
START:
    switch (mCharacter) {
            // Requirements: Blanks or tabs may appear anywhere except within unquoted labels or
            // branch_lengths.
        case ' ':
        case '\t':
        case '\r':
        case '\n':
            ignore();
            goto START;
            break;
        case ',':
            read();
            return Operator::COMMA;
        case '(':
            read();
            return Operator::LEFT_PARENTHESIS;
        case ')':
            read();
            return Operator::RIGHT_PARENTHESIS;
        case '[':
            while (mCharacter != ']') {
                read();
            }
            goto START;
        case ']':
            //            reset();
            read();
            goto INIT;
        case ':':
            mCharacter = ' ';
            return Operator::COLON;
        case ';':
            mCharacter = ' ';
            return Operator::SEMICOLON;
            //        case '\n':
            //            mCharacter = ' ';
            //            return Operator::END;
        default:
            // Exception?
            assert(0);
            break;
    }
    
LEADING_DIGIT:
    if (mCharacter == '-' || mCharacter == '+') {
        read();
    }
    if (isnumber(mCharacter)) {
        read();
        goto LEADING_DIGIT;
    } else if (mCharacter == '.') {
        read();
        goto TRAILING_DIGIT;
    } else {
        return Operator::NUMBER;
    }
TRAILING_DIGIT:
    if (isnumber(mCharacter)) {
        read();
        goto TRAILING_DIGIT;
    } else {
        return Operator::NUMBER;
    }
    
ALPHABET:
    while (isLabel(mCharacter)) {
        // Requirements: Underscore characters in unquoted labels are converted to blanks.
        if (mCharacter == '_') {
            mCharacter = ' ';
        }
        read();
    }
    return Operator::LABEL;
ALPHABET_WITH_QUOTATION_MARK:
    checkForQuotedLabel();
    while (mCharacter != 0) {
        readForQuotedLabel();
    }
    // Trim the string.
    mBuffer = trim_copy(mBuffer);
    return Operator::LABEL;
}