#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;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8c3RhY2s+CgojaW5jbHVkZSA8Y2N0eXBlPgojaW5jbHVkZSA8Y2Fzc2VydD4KCnN0cnVjdCBwYXJzZXJfc3RhdGUgewoJcGFyc2VyX3N0YXRlKGNvbnN0IHN0ZDo6c3RyaW5nJiBzdHIsIHNpemVfdCBwb3MpOgoJCXN0cihzdHIpLCBwb3MocG9zKSB7fQoJCglib29sIGVuZCAoKSBjb25zdCB7CgkJcmV0dXJuIHBvcyA+PSBzdHIuc2l6ZSgpOwoJfQoJCglib29sIHJlc3RvcmUgKGJvb2wgbWF0Y2hlZCkgewoJCWlmICghbWF0Y2hlZCkgcG9zID0gaGlzdG9yeS50b3AoKTsKCQloaXN0b3J5LnBvcCgpOwoJCXJldHVybiBtYXRjaGVkOwoJfQoJCglwYXJzZXJfc3RhdGUmIHNhdmUgKCkgewoJCWhpc3RvcnkucHVzaChwb3MpOwoJCXJldHVybiAqdGhpczsKCX0KCQoJY29uc3Qgc3RkOjpzdHJpbmcmIHN0cjsKCXN0ZDo6c3RhY2sgPHNpemVfdD4gaGlzdG9yeTsKCXNpemVfdCBwb3M7Cn07Cgpib29sIG1hdGNoX2RpZ2l0KHBhcnNlcl9zdGF0ZSYgcykgewoJaWYgKHMuZW5kKCkpIHJldHVybiBmYWxzZTsKCXJldHVybiBpc2RpZ2l0IChzLnN0cltzLnBvcysrXSk7Cn0KCmJvb2wgbWF0Y2hfZGlnaXRzKHBhcnNlcl9zdGF0ZSYgcykgewoJYm9vbCBtYXRjaGVkID0gZmFsc2U7Cgl3aGlsZSAobWF0Y2hfZGlnaXQocykpIG1hdGNoZWQgPSB0cnVlOwoJcmV0dXJuIG1hdGNoZWQ7Cn0KCmJvb2wgbWF0Y2hfc3ltYm9sKHBhcnNlcl9zdGF0ZSYgcywgY29uc3QgY2hhciogb3B0aW9ucykgewoJaWYgKHMuZW5kKCkpIHJldHVybiBmYWxzZTsKCXdoaWxlICgqb3B0aW9ucykgewoJCWlmIChzLnN0cltzLnBvc10gPT0gKm9wdGlvbnMpIGJyZWFrOwoJCW9wdGlvbnMgKys7Cgl9CglzLnBvcyArKzsKCXJldHVybiAqb3B0aW9ucyAhPSAnXDAnOwp9Cgpib29sIG1hdGNoX2ZyYWMocGFyc2VyX3N0YXRlJiBzKSB7CglyZXR1cm4gbWF0Y2hfc3ltYm9sKHMsICIuIikgJiYgbWF0Y2hfZGlnaXRzKHMpOwp9Cgpib29sIG1heWJlX21hdGNoX3NpZ24ocGFyc2VyX3N0YXRlJiBzKSB7CglzLnJlc3RvcmUobWF0Y2hfc3ltYm9sKHMuc2F2ZSgpLCAiKy0iKSk7CglyZXR1cm4gdHJ1ZTsKfQoKYm9vbCBtYXRjaF9leHBvbmVudChwYXJzZXJfc3RhdGUmIHMpIHsKCXJldHVybiBtYXRjaF9zeW1ib2wocywgIkVlIikgJiYgbWF5YmVfbWF0Y2hfc2lnbihzKSAmJiBtYXRjaF9kaWdpdHMocyk7Cn0KCmJvb2wgbWF0Y2hfbWFudGlzc2EocGFyc2VyX3N0YXRlJiBzKSB7CgltYXliZV9tYXRjaF9zaWduKHMpOwoJY29uc3QgYm9vbCBkaWdpdHMgPSBzLnJlc3RvcmUobWF0Y2hfZGlnaXRzKHMuc2F2ZSgpKSk7Cgljb25zdCBib29sIGZyYWMgPSBzLnJlc3RvcmUobWF0Y2hfZnJhYyhzLnNhdmUoKSkpOwoJaWYgKGZyYWMpIHJldHVybiB0cnVlOyAvLyAuMDAwIG9yIDAwMC4wMDAKCWlmICghZGlnaXRzKSByZXR1cm4gZmFsc2U7CglzLnJlc3RvcmUobWF0Y2hfc3ltYm9sKHMuc2F2ZSgpLCAiLiIpKTsKCXJldHVybiB0cnVlOyAvLyAwMDAgb3IgMDAwLgp9Cgpib29sIG1hdGNoX251bWJlcihwYXJzZXJfc3RhdGUmIHMpIHsKCWNvbnN0IGJvb2wgbSA9IHMucmVzdG9yZShtYXRjaF9tYW50aXNzYShzLnNhdmUoKSkpOwoJY29uc3QgYm9vbCBlID0gcy5yZXN0b3JlKG1hdGNoX2V4cG9uZW50KHMuc2F2ZSgpKSk7CglyZXR1cm4gKG0gfHwgZSkJJiYgcy5lbmQoKTsKfQoKYm9vbCBtYXRjaF9udW1iZXIoY29uc3Qgc3RkOjpzdHJpbmcmIHMpIHsKCXBhcnNlcl9zdGF0ZSBzdGF0ZShzLCAwKTsKCXJldHVybiBtYXRjaF9udW1iZXIoc3RhdGUpOwp9CgppbnQgbWFpbigpIHsKCXN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiBleGFtcGxlcyA9IHsKCQkiMCIsCgkJIiswIiwKCQkiMC4wMCIsCgkJIjAuIiwKCQkiLjAiLAoJCSIuIiwKCQkiMC5FMSIsCgkJIjAuRSsyIiwKCQkiLjBFKzMiLAoJCSIuMEUrMyAiLAoJCSIwLjAuIgoJfTsKCXBhcnNlcl9zdGF0ZSBzKCIiLCAwKTsKCXN0ZDo6Y291dCA8PCAobWF0Y2hfZXhwb25lbnQocykpIDw8IHN0ZDo6ZW5kbDsKCWZvciAoY29uc3QgYXV0byYgcyA6IGV4YW1wbGVzKSB7CgkJc3RkOjpjb3V0IDw8IHMgPDwgIjogIiA8PCBtYXRjaF9udW1iZXIocykgPDwgc3RkOjplbmRsOwoJfQoJcmV0dXJuIDA7Cn0=