fork download
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <stack>
  5.  
  6. #include <cctype>
  7. #include <cassert>
  8.  
  9. struct parser_state {
  10. parser_state(const std::string& str, size_t pos):
  11. str(str), pos(pos) {}
  12.  
  13. bool end () const {
  14. return pos >= str.size();
  15. }
  16.  
  17. bool restore (bool matched) {
  18. if (!matched) pos = history.top();
  19. history.pop();
  20. return matched;
  21. }
  22.  
  23. parser_state& save () {
  24. history.push(pos);
  25. return *this;
  26. }
  27.  
  28. const std::string& str;
  29. std::stack <size_t> history;
  30. size_t pos;
  31. };
  32.  
  33. bool match_digit(parser_state& s) {
  34. if (s.end()) return false;
  35. return isdigit (s.str[s.pos++]);
  36. }
  37.  
  38. bool match_digits(parser_state& s) {
  39. bool matched = false;
  40. while (s.restore(match_digit(s.save()))) matched = true;
  41. return matched;
  42. }
  43.  
  44. bool match_symbol(parser_state& s, const char* options) {
  45. if (s.end()) return false;
  46. while (*options) {
  47. if (s.str[s.pos] == *options) break;
  48. options ++;
  49. }
  50. s.pos ++;
  51. return *options != '\0';
  52. }
  53.  
  54. bool match_frac(parser_state& s) {
  55. return match_symbol(s, ".") && match_digits(s);
  56. }
  57.  
  58. bool maybe_match_sign(parser_state& s) {
  59. s.restore(match_symbol(s.save(), "+-"));
  60. return true;
  61. }
  62.  
  63. bool match_exponent(parser_state& s) {
  64. return match_symbol(s, "Ee") && maybe_match_sign(s) && match_digits(s);
  65. }
  66.  
  67. bool match_mantissa(parser_state& s) {
  68. maybe_match_sign(s);
  69. const bool digits = s.restore(match_digits(s.save()));
  70. const bool frac = s.restore(match_frac(s.save()));
  71. if (frac) return true; // .000 or 000.000
  72. if (!digits) return false; // not 000.000, not 000, not .000
  73. s.restore(match_symbol(s.save(), "."));
  74. return true; // 000 or 000.
  75. }
  76.  
  77. bool match_number(parser_state& s) {
  78. const bool m = s.restore(match_mantissa(s.save()));
  79. const bool e = s.restore(match_exponent(s.save()));
  80. return (m || e) && s.end();
  81. }
  82.  
  83. bool match_number(const std::string& s) {
  84. parser_state state(s, 0);
  85. return match_number(state);
  86. }
  87.  
  88. int main() {
  89. std::vector<std::pair<std::string, bool>> examples = {
  90. {"0" , true },
  91. {"+0" , true },
  92. {"0.0" , true },
  93. {"0." , true },
  94. {".0" , true },
  95. {"." , false},
  96. {"0.E1" , true },
  97. {"0.E+2" , true },
  98. {".0E+3" , true },
  99. {".0E+3 ", false},
  100. {"0.0." , false},
  101. {"0.." , false},
  102. {".0." , false},
  103. {"..0" , false},
  104. {"a" , false},
  105. {"+" , false},
  106. {"E" , false},
  107. {"E+" , false},
  108. {"+E" , false},
  109. {"+2E1" , true },
  110. {"++2E1" , false},
  111. };
  112. for (const auto& example : examples) {
  113. const bool matched = match_number(example.first);
  114. std::cout << example.first << ": " << matched << ", " << (matched == example.second ? "OK" : "ERROR") << std::endl;
  115. }
  116. return 0;
  117. }
Success #stdin #stdout 0s 4900KB
stdin
Standard input is empty
stdout
0: 1, OK
+0: 1, OK
0.0: 1, OK
0.: 1, OK
.0: 1, OK
.: 0, OK
0.E1: 1, OK
0.E+2: 1, OK
.0E+3: 1, OK
.0E+3 : 0, OK
0.0.: 0, OK
0..: 0, OK
.0.: 0, OK
..0: 0, OK
a: 0, OK
+: 0, OK
E: 0, OK
E+: 0, OK
+E: 0, OK
+2E1: 1, OK
++2E1: 0, OK