#include <iostream> #include <iomanip> #include <string> #include <set> #include <algorithm> #include <cctype> #include "token.h" using namespace std; // Public set<string> const Token::default_operators{ "+", "-", "*", "/", "%", "^", "=", "(", ")", "?", "£", "$" }; string const Token::default_separators{" \t\n\r"}; Token::Token(set<string> const& ops, string const& sep) : operators{ops}, separators{sep}, token{} { } istream& operator>>(istream& iss, Token& t) { return t.next(iss); } ostream& operator<<(ostream& oss, Token const& t) { return oss << t.token; } bool Token::is_operator() const { return operators.count( token ) == 1; } bool Token::is_integer() const { return all_of(token.begin(), token.end(), ::isdigit); } bool Token::is_decimal() const { bool valid_chars = all_of(token.begin(), token.end(), [](char c)->bool { return c == '.' || isdigit(c); }); bool one_dot = count(token.begin(), token.end(), '.') == 1; return valid_chars && one_dot; } bool Token::is_identifier() const { return all_of(token.begin(), token.end(), [](char c)->bool { return c == '_' || isalnum(c); }); } // Private bool Token::is_separator(int c) const { return ( separators.find(c) != string::npos ); } bool Token::is_delimeter(int c) const { if ( c == -1 ) // Traits::eof() return true; if ( is_separator( c ) ) return true; auto b{ operators.begin() }; auto e{ operators.end() }; for ( ; b != e; ++b ) { if ( b->at(0) == c ) return true; } return false; } bool Token::is_candidate() const { auto b{ operators.begin() }; auto e{ operators.end() }; for ( ; b != e; ++b ) { if ( b->find( token ) == 0 && *b != token ) return true; } return false; } void Token::append(int c) { token.push_back( static_cast<char>(c) ); } void Token::ignore_separators(istream& iss) { auto c{ iss.peek() }; while ( c != -1 ) // Traits::eof() { if ( ! is_separator( c ) ) return; iss.get(); c = iss.peek(); } } istream& Token::next(istream& iss) { token.clear(); ignore_separators( iss ); auto c{ iss.peek() }; bool prev_is_op{false}; while ( c != -1 ) // Traits::eof() { append( c ); bool is_op{ is_operator() }; bool is_can{ is_candidate() }; bool is_del{ is_delimeter(c) }; if ( is_op && ! is_can ) { iss.get(); return iss; } if ( prev_is_op && ! is_op && ! is_can ) { token.pop_back(); return iss; } if ( is_del && ! is_can ) { token.pop_back(); return iss; } prev_is_op = is_op; iss.get(); c = iss.peek(); } return iss; }