fork download
#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 (match_digit(s)) 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;
	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::string> examples = {
		"0",
		"+0",
		"0.00",
		"0.",
		".0",
		".",
		"0.E1",
		"0.E+2",
		".0E+3",
		".0E+3 ",
		"0.0."
	};
	parser_state s("", 0);
	std::cout << (match_exponent(s)) << std::endl;
	for (const auto& s : examples) {
		std::cout << s << ": " << match_number(s) << std::endl;
	}
	return 0;
}
Success #stdin #stdout 0s 4696KB
stdin
Standard input is empty
stdout
0
0: 1
+0: 1
0.00: 0
0.: 1
.0: 1
.: 0
0.E1: 1
0.E+2: 1
.0E+3: 0
.0E+3 : 0
0.0.: 0