/* * TokenGenerator.cc * * Created on: Feb 8, 2010 * Author: petergoodman * Version: $Id$ */ #include "TokenGenerator.h" // initialize the operator characters const string TokenGenerator::operators("+-*/=><"); /** * Constructor, initialize the token generator's set of operator characters * and the initial string to work on. */ TokenGenerator::TokenGenerator(const string &s) { str.assign(s); } /** * Destructor, auto-created. */ TokenGenerator::~TokenGenerator() { } /** * Change the string that the token generator is working on. */ void TokenGenerator::assign(const string &s) { str.assign(s); } /** * Generate the begin iterator for the string. */ TokenGenerator::iterator TokenGenerator::begin(void) throw(ParseError) { return iterator(str.begin(), str.end()); } /** * Generate the end iterator for the string. */ TokenGenerator::iterator TokenGenerator::end(void) throw(ParseError) { string::iterator end = str.end(); return iterator(end, end); } /* ------------------------------------------------------------------------ */ TokenGenerator::iterator::iterator(string::iterator begin, string::iterator end) throw(ParseError) { it = begin; it_end = end; curr = NULL; at_end = generateNext(); } TokenGenerator::iterator::~iterator() { } TokenGenerator::iterator::reference TokenGenerator::iterator::operator*() { return curr; } TokenGenerator::iterator &TokenGenerator::iterator::operator++ () { at_end = generateNext(); return *this; } TokenGenerator::iterator TokenGenerator::iterator::operator++ (int) { iterator tmp = *this; ++*this; return tmp; } bool TokenGenerator::iterator::operator!=(const iterator& other) { return it != other.it || at_end != other.at_end; } bool TokenGenerator::iterator::operator==(const iterator& other) { return it == other.it && at_end == other.at_end; } /** * Yield the next token from the token generator or throw an exception if * there is an error. */ bool TokenGenerator::iterator::generateNext() throw(ParseError) { bool has_separator = false; for(; it != it_end && isspace(*it); ++it, has_separator = true) { } if(it == it_end) { return true; } else if(!has_separator && NULL != curr) { // no separating whitespace stringstream sserr; sserr << "Expected space following token " << curr << ", got '"; for(; it != it_end && !isspace(*it); it++) { sserr << *it; } sserr << "' instead."; throw ParseError(sserr.str()); } // variable if(isalpha(*it)) { curr = parseAlphaNumName(Token::VARNAME); // integer } else if(isdigit(*it)) { curr = parseIntLiteral(); // operator } else if(operators.find(*it, 0) != string::npos) { curr = parseOperator(); // function } else if('.' == *it) { it++; if(it == it_end || !isalpha(*it)) { throw ParseError( "Expected system function name following '.'." ); } curr = parseAlphaNumName(Token::FUNCTION); // string } else if('"' == *it) { curr = parseStringLiteral(); // error } else { stringstream sserr; sserr << "Unexpected input character '" << *it << "'."; throw ParseError(sserr.str()); } return false; } /** * Parse an integer literal. */ Token *TokenGenerator::iterator::parseIntLiteral() { stringstream ss; int value = 0; for(; it != it_end && isdigit(*it); it++) { ss << *it; } ss >> value; return new Token(Token::INT, value); } /** * Parse a string literal. */ Token *TokenGenerator::iterator::parseStringLiteral() { stringstream ss; it++; for(; it != it_end && *it != '"'; it++) { if(*it == '\\') { if((it + 1) == it_end) { throw ParseError("Unterminated string literal at end of line."); } it++; } ss << *it; } if(it == it_end) { throw ParseError("Unterminated string literal at end of line."); } it++; // move past the ending quote return new Token(Token::STRING, ss.str()); } /** * Parse a sequence of alphabetical characters. */ Token *TokenGenerator::iterator::parseAlphaNumName(const Token::Type type) { stringstream ss; for(bool not_first = false; it != it_end && (isalpha(*it) || (not_first && isdigit(*it))); it++, not_first = true) { ss << *it; } return new Token(type, ss.str()); } /** * Parse an operator. */ Token *TokenGenerator::iterator::parseOperator() { stringstream ss; ss << *it; it++; if(it != it_end && *it == '=') { ss << *it; it++; } return new Token(Token::OPERATOR, ss.str()); }