Last active
February 14, 2022 20:03
-
-
Save NickAger/d58f3120388fe899cad1022a01c162b9 to your computer and use it in GitHub Desktop.
Attempt to simplify parsing code shown in https://github.com/fivemoreminix/rsc but didn't work
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use std::fmt; | |
| use rsc::{tokenize, parse, Interpreter, TokenizeError, ParseError, InterpretError}; | |
| // error handling based on: | |
| // * https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/wrap_error.html | |
| // Unfortunately this didn't work in the context of `fn evaluate` as: | |
| // 1) `cannot return value referencing local variable `tokens`` | |
| // 2) `cannot return value referencing local variable `expr`` | |
| // `ParseError` contains a reference to a Token rather than copy of it | |
| // I tried to change `ParseErrorCode::UnexpectedToken` to contain a copy of a `Token` | |
| // rather than a reference to a `Token` but `Token` contains a range which is uncopyable. | |
| // https://users.rust-lang.org/t/why-doesnt-range-t-copy-implement-copy/51224 | |
| #[derive(Debug)] | |
| enum EquationError<'input_string> { | |
| Tokenize(TokenizeError<'input_string>), | |
| Parse(ParseError<'input_string, f64>), | |
| Interpret(InterpretError<'input_string>) | |
| } | |
| impl<'input_string> From<TokenizeError<'input_string>> for EquationError<'input_string> { | |
| fn from(err: TokenizeError<'input_string>) -> EquationError<'input_string> { | |
| EquationError::Tokenize(err) | |
| } | |
| } | |
| impl<'input_string> From<ParseError<'input_string, f64>> for EquationError<'input_string> { | |
| fn from(err: ParseError<'input_string, f64>) -> EquationError<'input_string> { | |
| EquationError::Parse(err) | |
| } | |
| } | |
| impl<'input_string> From<InterpretError<'input_string>> for EquationError<'input_string> { | |
| fn from(err: InterpretError<'input_string>) -> EquationError<'input_string> { | |
| EquationError::Interpret(err) | |
| } | |
| } | |
| impl fmt::Display for EquationError<'_> { | |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| match self { | |
| EquationError::Tokenize(token_error) => | |
| write!(f, "Tokenize Error: {:?}", token_error), | |
| EquationError::Parse(parse_error) => | |
| write!(f, "Parse Error: {:?}", parse_error), | |
| EquationError::Interpret(interpret_error) => | |
| write!(f, "Interpret Error: {:?}", interpret_error) | |
| } | |
| } | |
| } | |
| /* | |
| original evaluate | |
| fn evaluate(input: &str, interpreter: &mut Interpreter<f64>) -> Result<f64, ()> { | |
| // You have to call each function in the pipeline, but this gives you the most | |
| // control over error handling and performance. | |
| match tokenize(input) { // Step 1: splits input into symbols, words, and numbers | |
| Ok(tokens) => match parse(&tokens) { // Step 2: builds an Expr using tokens | |
| Ok(expr) => match interpreter.eval(&expr) { // Step 3: interprets the Expr | |
| Ok(result) => println!("{}", result), | |
| Err(interpret_error) => eprintln!("{:?}", interpret_error), | |
| }, | |
| Err(parse_error) => eprintln!("{:?}", parse_error), | |
| }, | |
| Err(tokenize_error) => eprintln!("{:?}", tokenize_error), | |
| } | |
| } | |
| */ | |
| type EvaluateResult<'input> = std::result::Result<f64, EquationError<'input>>; | |
| fn evaluate<'input>(input: &'input str, interpreter: &mut Interpreter<f64>) -> EvaluateResult<'input> { | |
| let tokens = tokenize(&input)?; | |
| let expr = parse(&tokens)?; | |
| let result = interpreter.eval(&expr)?; | |
| return Ok(result); | |
| } | |
| fn main() { | |
| // Constructs an f64 interpreter with included variables | |
| let mut interpreter = Interpreter::default(); | |
| evaluate("5^2", &mut interpreter); // prints "25" | |
| evaluate("x = 3", &mut interpreter); // prints "3" | |
| evaluate("x(3) + 1", &mut interpreter); // prints "10" | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment