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 (match_digit(s)) 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;
  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::string> examples = {
  90. "0",
  91. "+0",
  92. "0.00",
  93. "0.",
  94. ".0",
  95. ".",
  96. "0.E1",
  97. "0.E+2",
  98. ".0E+3",
  99. ".0E+3 ",
  100. "0.0."
  101. };
  102. parser_state s("", 0);
  103. std::cout << (match_exponent(s)) << std::endl;
  104. for (const auto& s : examples) {
  105. std::cout << s << ": " << match_number(s) << std::endl;
  106. }
  107. return 0;
  108. }
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