#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 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8c3RhY2s+CgojaW5jbHVkZSA8Y2N0eXBlPgojaW5jbHVkZSA8Y2Fzc2VydD4KCnN0cnVjdCBwYXJzZXJfc3RhdGUgewoJcGFyc2VyX3N0YXRlKGNvbnN0IHN0ZDo6c3RyaW5nJiBzdHIsIHNpemVfdCBwb3MpOgoJCXN0cihzdHIpLCBwb3MocG9zKSB7fQoJCglib29sIGVuZCAoKSBjb25zdCB7CgkJcmV0dXJuIHBvcyA+PSBzdHIuc2l6ZSgpOwoJfQoJCglib29sIHJlc3RvcmUgKGJvb2wgbWF0Y2hlZCkgewoJCWlmICghbWF0Y2hlZCkgcG9zID0gaGlzdG9yeS50b3AoKTsKCQloaXN0b3J5LnBvcCgpOwoJCXJldHVybiBtYXRjaGVkOwoJfQoJCglwYXJzZXJfc3RhdGUmIHNhdmUgKCkgewoJCWhpc3RvcnkucHVzaChwb3MpOwoJCXJldHVybiAqdGhpczsKCX0KCQoJY29uc3Qgc3RkOjpzdHJpbmcmIHN0cjsKCXN0ZDo6c3RhY2sgPHNpemVfdD4gaGlzdG9yeTsKCXNpemVfdCBwb3M7Cn07Cgpib29sIG1hdGNoX2RpZ2l0KHBhcnNlcl9zdGF0ZSYgcykgewoJaWYgKHMuZW5kKCkpIHJldHVybiBmYWxzZTsKCXJldHVybiBpc2RpZ2l0IChzLnN0cltzLnBvcysrXSk7Cn0KCmJvb2wgbWF0Y2hfZGlnaXRzKHBhcnNlcl9zdGF0ZSYgcykgewoJYm9vbCBtYXRjaGVkID0gZmFsc2U7Cgl3aGlsZSAocy5yZXN0b3JlKG1hdGNoX2RpZ2l0KHMuc2F2ZSgpKSkpIG1hdGNoZWQgPSB0cnVlOwoJcmV0dXJuIG1hdGNoZWQ7Cn0KCmJvb2wgbWF0Y2hfc3ltYm9sKHBhcnNlcl9zdGF0ZSYgcywgY29uc3QgY2hhciogb3B0aW9ucykgewoJaWYgKHMuZW5kKCkpIHJldHVybiBmYWxzZTsKCXdoaWxlICgqb3B0aW9ucykgewoJCWlmIChzLnN0cltzLnBvc10gPT0gKm9wdGlvbnMpIGJyZWFrOwoJCW9wdGlvbnMgKys7Cgl9CglzLnBvcyArKzsKCXJldHVybiAqb3B0aW9ucyAhPSAnXDAnOwp9Cgpib29sIG1hdGNoX2ZyYWMocGFyc2VyX3N0YXRlJiBzKSB7CglyZXR1cm4gbWF0Y2hfc3ltYm9sKHMsICIuIikgJiYgbWF0Y2hfZGlnaXRzKHMpOwp9Cgpib29sIG1heWJlX21hdGNoX3NpZ24ocGFyc2VyX3N0YXRlJiBzKSB7CglzLnJlc3RvcmUobWF0Y2hfc3ltYm9sKHMuc2F2ZSgpLCAiKy0iKSk7CglyZXR1cm4gdHJ1ZTsKfQoKYm9vbCBtYXRjaF9leHBvbmVudChwYXJzZXJfc3RhdGUmIHMpIHsKCXJldHVybiBtYXRjaF9zeW1ib2wocywgIkVlIikgJiYgbWF5YmVfbWF0Y2hfc2lnbihzKSAmJiBtYXRjaF9kaWdpdHMocyk7Cn0KCmJvb2wgbWF0Y2hfbWFudGlzc2EocGFyc2VyX3N0YXRlJiBzKSB7CgltYXliZV9tYXRjaF9zaWduKHMpOwoJY29uc3QgYm9vbCBkaWdpdHMgPSBzLnJlc3RvcmUobWF0Y2hfZGlnaXRzKHMuc2F2ZSgpKSk7Cgljb25zdCBib29sIGZyYWMgPSBzLnJlc3RvcmUobWF0Y2hfZnJhYyhzLnNhdmUoKSkpOwoJaWYgKGZyYWMpIHJldHVybiB0cnVlOyAvLyAuMDAwIG9yIDAwMC4wMDAKCWlmICghZGlnaXRzKSByZXR1cm4gZmFsc2U7IC8vIG5vdCAwMDAuMDAwLCBub3QgMDAwLCBub3QgLjAwMAoJcy5yZXN0b3JlKG1hdGNoX3N5bWJvbChzLnNhdmUoKSwgIi4iKSk7CglyZXR1cm4gdHJ1ZTsgLy8gMDAwIG9yIDAwMC4KfQoKYm9vbCBtYXRjaF9udW1iZXIocGFyc2VyX3N0YXRlJiBzKSB7Cgljb25zdCBib29sIG0gPSBzLnJlc3RvcmUobWF0Y2hfbWFudGlzc2Eocy5zYXZlKCkpKTsKCWNvbnN0IGJvb2wgZSA9IHMucmVzdG9yZShtYXRjaF9leHBvbmVudChzLnNhdmUoKSkpOwoJcmV0dXJuIChtIHx8IGUpICYmIHMuZW5kKCk7Cn0KCmJvb2wgbWF0Y2hfbnVtYmVyKGNvbnN0IHN0ZDo6c3RyaW5nJiBzKSB7CglwYXJzZXJfc3RhdGUgc3RhdGUocywgMCk7CglyZXR1cm4gbWF0Y2hfbnVtYmVyKHN0YXRlKTsKfQoKaW50IG1haW4oKSB7CglzdGQ6OnZlY3RvcjxzdGQ6OnBhaXI8c3RkOjpzdHJpbmcsIGJvb2w+PiBleGFtcGxlcyA9IHsKCQl7IjAiICAgICAsIHRydWUgfSwKCQl7IiswIiAgICAsIHRydWUgfSwKCQl7IjAuMCIgICAsIHRydWUgfSwKCQl7IjAuIiAgICAsIHRydWUgfSwKCQl7Ii4wIiAgICAsIHRydWUgfSwKCQl7Ii4iICAgICAsIGZhbHNlfSwKCQl7IjAuRTEiICAsIHRydWUgfSwKCQl7IjAuRSsyIiAsIHRydWUgfSwKCQl7Ii4wRSszIiAsIHRydWUgfSwKCQl7Ii4wRSszICIsIGZhbHNlfSwKCQl7IjAuMC4iICAsIGZhbHNlfSwKCQl7IjAuLiIgICAsIGZhbHNlfSwKCQl7Ii4wLiIgICAsIGZhbHNlfSwKCQl7Ii4uMCIgICAsIGZhbHNlfSwKCQl7ImEiICAgICAsIGZhbHNlfSwKCQl7IisiICAgICAsIGZhbHNlfSwKCQl7IkUiICAgICAsIGZhbHNlfSwKCQl7IkUrIiAgICAsIGZhbHNlfSwKCQl7IitFIiAgICAsIGZhbHNlfSwKCQl7IisyRTEiICAsIHRydWUgfSwKCQl7IisrMkUxIiAsIGZhbHNlfSwKCX07Cglmb3IgKGNvbnN0IGF1dG8mIGV4YW1wbGUgOiBleGFtcGxlcykgewoJCWNvbnN0IGJvb2wgbWF0Y2hlZCA9IG1hdGNoX251bWJlcihleGFtcGxlLmZpcnN0KTsKCQlzdGQ6OmNvdXQgPDwgZXhhbXBsZS5maXJzdCA8PCAiOiAiIDw8IG1hdGNoZWQgPDwgIiwgIiA8PCAobWF0Y2hlZCA9PSBleGFtcGxlLnNlY29uZCA/ICJPSyIgOiAiRVJST1IiKSA8PCBzdGQ6OmVuZGw7Cgl9CglyZXR1cm4gMDsKfQ==