Calculator Step 1

- Main Page
- Classes
- Files

- Class List
- Class Index
- Class Hierarchy
- Class Members

Public Member Functions | Private Member Functions | Private Attributes | List of all members
parser Class Reference

`#include <parse.hpp>`

## Public Member Functions
| parser (std::istream &input)
bool | get_expr (double &result)

## Private Member Functions
std::string | charify (char c)
bool | get_number (double &result)
bool | get_primary (double &result)
bool | get_mult_expr (double &result)

## Private Attributes
std::istream & | input_
std::ctype< char > const & | ctype_

## Detailed Description

Parser class template.

Definition at line 17 of file parse.hpp.

## Constructor & Destructor Documentation

parser::parser | ( | std::istream & | input | ) |

Constructor. Save the `input` stream.

Parameters

  input | The input stream

Definition at line 6 of file parse.cpp.

7 : input_(input),
8 ctype_(std::use_facet<std::ctype<char>>(input.getloc()))
9 {}
parser::input_
std::istream & input_
Definition: parse.hpp:55
parser::ctype_
std::ctype< char > const & ctype_
Definition: parse.hpp:56

## Member Function Documentation

std::string parser::charify | ( | char | c | ) |
| private

Convert a characer to a readable form.

Parameters

  c | The character

Returns
  A C++-style character literal that ensures `c` is readable.

Definition at line 11 of file parse.cpp.

Referenced by get_number(), and get_primary().

12 {
13 if (c == '\a') return R"('\a')";
14 if (c == '\b') return R"('\b')";
15 if (c == '\f') return R"('\f')";
16 if (c == '\n') return R"('\n')";
17 if (c == '\r') return R"('\r')";
18 if (c == '\t') return R"('\t')";
19 if (c == '\v') return R"('\v')";
20 if (c == '\'') return R"('\'')";
21 if (c == '\\') return R"('\\')";
22
23 if (isprint(c))
24 return std::string{"\'"} + std::string(1,c) + "\'";
25 else {
26 std::ostringstream stream{};
27 stream << "'\\x" << std::hex;
28 stream.fill('0');
29 stream.width(2);
30 stream << (std::char_traits<char>::to_int_type(c) & 0xFF) << '\'';
31 return stream.str();
32 }
33 }

bool parser::get_expr | ( | double & | result | ) |

Read one expression and store the result in `result`.

Parameters

  result | Where to store the result of the expression.

Returns
  true to continue or false to end the loop

Exceptions

  parse_error | for various syntax and other errors

Definition at line 110 of file parse.cpp.

References get_mult_expr(), and input_.

Referenced by get_primary().

111 {
112 if (not get_mult_expr(result))
113 return false;
114 char c{};
115 while (input_ >> c) {
116 if (c != '+' and c != '-') {
117 input_.unget();
118 return true;
119 } else {
120 double right{};
121 if (not get_mult_expr(right))
122 throw parse_error{"syntax error: unterminated expression. Expected a multiplicative-exprssion after " + std::string(c,1)};
123 if (c == '+')
124 result += right;
125 else
126 result -= right;
127 }
128 }
129 return true;
130 }
parse_error
Definition: parse.hpp:11
parser::input_
std::istream & input_
Definition: parse.hpp:55
parser::get_mult_expr
bool get_mult_expr(double &result)
Definition: parse.cpp:135

bool parser::get_mult_expr | ( | double & | result | ) |
| private

Parse a multiplicative expression.

Parameters

  result | Store the number here

Returns
  true to continue parsing or false to stop (end of file or error)

Definition at line 135 of file parse.cpp.

References get_primary(), and input_.

Referenced by get_expr().

136 {
137 if (not get_primary(result))
138 return false;
139 char c{};
140 while (input_ >> c) {
141 if (c != '*' and c != '/') {
142 input_.unget();
143 return true;
144 } else {
145 double right{};
146 if (not get_primary(right))
147 throw parse_error{"syntax error: unterminated expression. Expected a primary after " + std::string(c,1)};
148 if (c == '*')
149 result *= right;
150 else if (right == 0.0)
151 throw parse_error{"division by zero"};
152 else
153 result /= right;
154 }
155 }
156 return true;
157 }
parser::get_primary
bool get_primary(double &result)
Definition: parse.cpp:162
parse_error
Definition: parse.hpp:11
parser::input_
std::istream & input_
Definition: parse.hpp:55

bool parser::get_number | ( | double & | result | ) |
| private

Parse a number.

Parameters

  result | Store the number here

Returns
  true to continue parsing or false to stop (end of file or error)

Definition at line 38 of file parse.cpp.

References charify(), and input_.

Referenced by get_primary().

39 {
40 std::string token{};
41 char c{};
42 if (not input_.get(c))
43 return false;
44 if (c == '+' or c == '-') {
45 token += c;
46 if (not input_.get(c))
47 throw parse_error{"unterminated number: expected a digit after the sign"};
48 }
49 if (c < '0' or c > '9') {
50 input_.unget();
51 throw parse_error{"syntax error: expected digit, got " + charify(c)};
52 }
53 while (c >= '0' and c <= '9') {
54 token += c;
55 if (not input_.get(c)) {
56 std::istringstream tmp{std::move(token)};
57 // If the value overflows, return false.
58 return (tmp >> result);
59 }
60 }
61 if (c == '.') {
62 token += c;
63 if (not input_.get(c))
64 throw parse_error{"unterminated number: expected digit after the decimal point"};
65 if (c < '0' or c > '9') {
66 input_.unget();
67 throw parse_error{"syntax error: expected digit after decimal point, got " + charify(c)};
68 }
69 while (c >= '0' and c <= '9') {
70 token += c;
71 if (not input_.get(c)) {
72 std::istringstream tmp{std::move(token)};
73 // If the value overflows or is otherwise invalid, return false.
74 return (tmp >> result);
75 }
76 }
77 }
78 if (c == 'e' or c == 'E') {
79 token += c;
80 if (not input_.get(c))
81 throw parse_error{"unterminated number: expected digit in the exponent"};
82 if (c == '-' or c == '+') {
83 token += c;
84 if (not input_.get(c))
85 throw parse_error{"unterminated number: expected digit after sign in the exponent"};
86 }
87 if (c < '0' or c > '9') {
88 input_.unget();
89 throw parse_error{"syntax error: expected digit in the exponent, got " + charify(c)};
90 }
91 while (c >= '0' and c <= '9') {
92 token += c;
93 if (not input_.get(c)) {
94 std::istringstream tmp{std::move(token)};
95 // If the value overflows or is otherwise invalid, return false.
96 return (tmp >> result);
97 }
98 }
99 }
100 input_.unget();
101
102 std::istringstream tmp{std::move(token)};
103 // If the value overflows or is otherwise invalid, return false.
104 return (tmp >> result);
105 }
parser::charify
std::string charify(char c)
Definition: parse.cpp:11
parse_error
Definition: parse.hpp:11
parser::input_
std::istream & input_
Definition: parse.hpp:55

bool parser::get_primary | ( | double & | result | ) |
| private

Parse a primary expression. A primary is a parenthesized expression or a numeric literal.

Parameters

  result | Store the number here

Returns
  true to continue parsing or false to stop (end of file or error)

Definition at line 162 of file parse.cpp.

References charify(), get_expr(), get_number(), and input_.

Referenced by get_mult_expr().

163 {
164 char c{};
165 if (not (input_ >> c))
166 // Can't read one character, so must be end-of-file
167 return false;
168 else if (c == '(') {
169 if (not get_expr(result))
170 return false;
171 if (not (input_ >> c))
172 throw parse_error{"syntax error: EOF when expecting ')'"};
173 else if (c != ')')
174 throw parse_error{"syntax error: expected ')', but got " + charify(c)};
175 else
176 return true;
177 } else {
178 input_.unget();
179 return get_number(result);
180 }
181 }
parser::charify
std::string charify(char c)
Definition: parse.cpp:11
parser::get_number
bool get_number(double &result)
Definition: parse.cpp:38
parser::get_expr
bool get_expr(double &result)
Definition: parse.cpp:110
parse_error
Definition: parse.hpp:11
parser::input_
std::istream & input_
Definition: parse.hpp:55

## Member Data Documentation

std::ctype<char> const& parser::ctype_
| private

Definition at line 56 of file parse.hpp.

std::istream& parser::input_
| private

Definition at line 55 of file parse.hpp.

Referenced by get_expr(), get_mult_expr(), get_number(), and get_primary().

The documentation for this class was generated from the following files:

- parse.hpp
- parse.cpp