fork download
  1. #include <cctype>
  2. #include <iostream>
  3. #include <stdexcept>
  4. #include <string>
  5.  
  6. struct parse_error : std::runtime_error
  7. {
  8. parse_error(std::string const& what)
  9. : runtime_error(what)
  10. {}
  11. };
  12.  
  13. void skip_spaces(char const*& line)
  14. {
  15. while(std::isspace(*line))
  16. ++line;
  17. }
  18.  
  19. // primary-expression = number | '(' sum ')'
  20. // product = primary-expression ['*' | '/' product]
  21. // sum = product ['+' | '-' sum]
  22.  
  23. double parse_number(char const*& line)
  24. {
  25. return std::strtod(line, const_cast<char**>(&line));
  26. }
  27.  
  28. double parse_sum(char const*& line);
  29.  
  30. double parse_primary_expression(char const*& line)
  31. {
  32. skip_spaces(line);
  33.  
  34. if(*line == '(')
  35. {
  36. double result = parse_sum(++line);
  37. skip_spaces(line);
  38.  
  39. if(*line != ')')
  40. throw parse_error("expected closing parenthesis here: " + std::string(line));
  41.  
  42. ++line;
  43. return result;
  44. }
  45.  
  46. else if(std::isdigit(*line))
  47. return parse_number(line);
  48. }
  49.  
  50. double parse_product(char const*& line)
  51. {
  52. double first = parse_primary_expression(line);
  53. skip_spaces(line);
  54.  
  55. for(;;)
  56. {
  57. skip_spaces(line);
  58.  
  59. if(*line == '*')
  60. first *= parse_primary_expression(++line);
  61. else if(*line == '/')
  62. first /= parse_primary_expression(++line);
  63. else break;
  64. }
  65.  
  66. return first;
  67. }
  68.  
  69. double parse_sum(char const*& line)
  70. {
  71. double first = parse_product(line);
  72.  
  73. for(;;)
  74. {
  75. skip_spaces(line);
  76.  
  77. if(*line == '+')
  78. first += parse_product(++line);
  79. else if(*line == '-')
  80. first -= parse_product(++line);
  81. else break;
  82. }
  83.  
  84. return first;
  85. }
  86.  
  87. double parse(char const* line)
  88. {
  89. double result = parse_sum(line);
  90. skip_spaces(line);
  91.  
  92. if(*line)
  93. throw parse_error("unexpected character here: " + std::string(line));
  94.  
  95. return result;
  96. }
  97.  
  98. int main()
  99. {
  100. for(std::string line; std::getline(std::cin, line);)
  101. {
  102. try
  103. {
  104. std::cout << parse(line.c_str()) << '\n';
  105. }
  106.  
  107. catch(parse_error const& e)
  108. {
  109. std::cout << e.what() << '\n';
  110. }
  111. }
  112. }
Success #stdin #stdout 0s 3024KB
stdin
2+2
3-2*1+5
2*(3+4)
foo
4*a
stdout
4
6
14
unexpected character here: foo
unexpected character here: a