#include <iostream>
#include <string>
#include <vector>
#include <stack>

#include <cctype>
#include <cassert>

struct parser_state {
	parser_state(const std::string& str, size_t pos):
		str(str), pos(pos) {}
	
	bool end () const {
		return pos >= str.size();
	}
	
	bool restore (bool matched) {
		if (!matched) pos = history.top();
		history.pop();
		return matched;
	}
	
	parser_state& save () {
		history.push(pos);
		return *this;
	}
	
	const std::string& str;
	std::stack <size_t> history;
	size_t pos;
};

bool match_digit(parser_state& s) {
	if (s.end()) return false;
	return isdigit (s.str[s.pos++]);
}

bool match_digits(parser_state& s) {
	bool matched = false;
	while (s.restore(match_digit(s.save()))) matched = true;
	return matched;
}

bool match_symbol(parser_state& s, const char* options) {
	if (s.end()) return false;
	while (*options) {
		if (s.str[s.pos] == *options) break;
		options ++;
	}
	s.pos ++;
	return *options != '\0';
}

bool match_frac(parser_state& s) {
	return match_symbol(s, ".") && match_digits(s);
}

bool maybe_match_sign(parser_state& s) {
	s.restore(match_symbol(s.save(), "+-"));
	return true;
}

bool match_exponent(parser_state& s) {
	return match_symbol(s, "Ee") && maybe_match_sign(s) && match_digits(s);
}

bool match_mantissa(parser_state& s) {
	maybe_match_sign(s);
	const bool digits = s.restore(match_digits(s.save()));
	const bool frac = s.restore(match_frac(s.save()));
	if (frac) return true; // .000 or 000.000
	if (!digits) return false; // not 000.000, not 000, not .000
	s.restore(match_symbol(s.save(), "."));
	return true; // 000 or 000.
}

bool match_number(parser_state& s) {
	const bool m = s.restore(match_mantissa(s.save()));
	const bool e = s.restore(match_exponent(s.save()));
	return (m || e) && s.end();
}

bool match_number(const std::string& s) {
	parser_state state(s, 0);
	return match_number(state);
}

int main() {
	std::vector<std::pair<std::string, bool>> examples = {
		{"0"     , true },
		{"+0"    , true },
		{"0.0"   , true },
		{"0."    , true },
		{".0"    , true },
		{"."     , false},
		{"0.E1"  , true },
		{"0.E+2" , true },
		{".0E+3" , true },
		{".0E+3 ", false},
		{"0.0."  , false},
		{"0.."   , false},
		{".0."   , false},
		{"..0"   , false},
		{"a"     , false},
		{"+"     , false},
		{"E"     , false},
		{"E+"    , false},
		{"+E"    , false},
		{"+2E1"  , true },
		{"++2E1" , false},
	};
	for (const auto& example : examples) {
		const bool matched = match_number(example.first);
		std::cout << example.first << ": " << matched << ", " << (matched == example.second ? "OK" : "ERROR") << std::endl;
	}
	return 0;
}