math_calc/lib.rs
1//! # About
2//!
3//! Welcome to the documentation for `math-calc`! This is a simple arithmatic
4//! library that gets an inputted [String], [u8] slice or a plain [&str](str)
5//! and outputs the finished calculation.
6//!
7//! This essentially means you can input multiple calculations seperated by a
8//! `,` (similar to how JSON can be used) and get a [Vec]<[i32]> containing the
9//! finished calculations.
10//!
11//! # Examples
12//!
13//! A basic parsing of a `&str` directly:
14//!
15//! ```rust
16//! use math_calc::{ErrorKind, parse_str};
17//!
18//! fn main() {
19//! // Expected returns: 1st: 3, 2nd: 110, 3rd: 123
20//! let inputted_calculations = "1 + 2, 550 / 5, 8 * 16 + (-25 / 5)";
21//!
22//! // Generate results
23//! let output_vec: Vec<i32> = parse_str(inputted_calculations).unwrap();
24//!
25//! // Output results of calculation
26//! println!("Calculation results (in vector):\n\n{:?}", output_vec);
27//! }
28//! ```
29
30#[macro_use]
31extern crate lalrpop_util;
32
33use std::str;
34
35lalrpop_mod!(grammar);
36
37/// Primary error enum that is used on frontend functions to enable proper
38/// error parsing downstream.
39///
40/// - [ErrorKind::ParseError]: The result when the parser has trouble
41/// understanding the inputted string.
42/// - [ErrorKind::InvalidInputEncoding]: When a given input is encoded poorly.
43/// **Make sure `input` in [parse_str] is UTF-8!**
44#[derive(Debug)]
45pub enum ErrorKind<'a> {
46 ParseError(lalrpop_util::ParseError<usize, grammar::Token<'a>, &'a str>),
47 InvalidInputEncoding(std::str::Utf8Error),
48}
49
50/// Parses a given [u8] slice into the expected [Vec]<[i32]> result.
51///
52/// # Examples
53///
54/// Basic valid [u8] slice parsing:
55///
56/// ```rust
57/// use math_calc::{ErrorKind, parse_u8_slice};
58///
59/// fn main() {
60/// // Says "(90 + 5) / 5". Should result in `19`.
61/// let my_slice = &[40, 53, 32, 43, 32, 57, 48, 41, 32, 47, 32, 53];
62///
63/// // Parse `my_slice` into the resulting i32 vector
64/// let output_vec: Vec<i32> = parse_u8_slice(my_slice).unwrap();
65///
66/// // Outputs the final i32 vector
67/// println!("Calculation results (in vector):\n\n{:?}", output_vec);
68/// }
69/// ```
70///
71/// Error handling for an invalid u8 formatting (needs to be valid `UTF-8`):
72///
73/// ```rust
74/// use math_calc::{ErrorKind, parse_u8_slice};
75///
76/// fn main() {
77/// // Invalid due to bad formatting (`255` is not a valid character).
78/// let bad_formatting = &[255, 255, 255, 255, 255, 255, 255, 255, 255];
79///
80/// // A test assert to prove threoy
81/// assert!(parse_u8_slice(bad_formatting).is_err())
82/// }
83/// ```
84pub fn parse_u8_slice(input: &[u8]) -> Result<Vec<i32>, ErrorKind> {
85 let input_str = match str::from_utf8(input) {
86 Ok(x) => x,
87 Err(e) => return Err(ErrorKind::InvalidInputEncoding(e)),
88 };
89
90 parse_str(input_str)
91}
92
93/// Parses a given [str] into the expected [Vec]<[i32]> result.
94///
95/// ***NOTE: This is the primary function that other `parse_x()` functions hook onto***.
96///
97/// # Examples
98///
99/// ```rust
100/// use math_calc::{ErrorKind, parse_str};
101///
102/// fn main() {
103/// let test_operation = "12 + 24, 5 + (4 / (2 + 2))"; // 1: 36, 2: 6
104///
105/// println!(
106/// "Result of operation: {:?}",
107/// parse_str(&test_operation).unwrap()
108/// );
109/// }
110/// ```
111pub fn parse_str(arithmatic: &str) -> Result<Vec<i32>, ErrorKind> {
112 match grammar::GrammarParser::new().parse(arithmatic) {
113 Ok(x) => Ok(x),
114 Err(e) => Err(ErrorKind::ParseError(e)),
115 }
116}