16855e09eSopenharmony_ciuse std::fmt; 26855e09eSopenharmony_ciuse std::fmt::{Debug, Display, Formatter}; 36855e09eSopenharmony_ci 46855e09eSopenharmony_ciuse std::str::FromStr; 56855e09eSopenharmony_ci 66855e09eSopenharmony_ciuse nom::{ 76855e09eSopenharmony_ci branch::alt, 86855e09eSopenharmony_ci bytes::complete::tag, 96855e09eSopenharmony_ci character::complete::{digit1 as digit, multispace0 as multispace}, 106855e09eSopenharmony_ci combinator::{map, map_res}, 116855e09eSopenharmony_ci multi::many0, 126855e09eSopenharmony_ci sequence::{delimited, preceded}, 136855e09eSopenharmony_ci IResult, 146855e09eSopenharmony_ci}; 156855e09eSopenharmony_ci 166855e09eSopenharmony_cipub enum Expr { 176855e09eSopenharmony_ci Value(i64), 186855e09eSopenharmony_ci Add(Box<Expr>, Box<Expr>), 196855e09eSopenharmony_ci Sub(Box<Expr>, Box<Expr>), 206855e09eSopenharmony_ci Mul(Box<Expr>, Box<Expr>), 216855e09eSopenharmony_ci Div(Box<Expr>, Box<Expr>), 226855e09eSopenharmony_ci Paren(Box<Expr>), 236855e09eSopenharmony_ci} 246855e09eSopenharmony_ci 256855e09eSopenharmony_ci#[derive(Debug)] 266855e09eSopenharmony_cipub enum Oper { 276855e09eSopenharmony_ci Add, 286855e09eSopenharmony_ci Sub, 296855e09eSopenharmony_ci Mul, 306855e09eSopenharmony_ci Div, 316855e09eSopenharmony_ci} 326855e09eSopenharmony_ci 336855e09eSopenharmony_ciimpl Display for Expr { 346855e09eSopenharmony_ci fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result { 356855e09eSopenharmony_ci use self::Expr::*; 366855e09eSopenharmony_ci match *self { 376855e09eSopenharmony_ci Value(val) => write!(format, "{}", val), 386855e09eSopenharmony_ci Add(ref left, ref right) => write!(format, "{} + {}", left, right), 396855e09eSopenharmony_ci Sub(ref left, ref right) => write!(format, "{} - {}", left, right), 406855e09eSopenharmony_ci Mul(ref left, ref right) => write!(format, "{} * {}", left, right), 416855e09eSopenharmony_ci Div(ref left, ref right) => write!(format, "{} / {}", left, right), 426855e09eSopenharmony_ci Paren(ref expr) => write!(format, "({})", expr), 436855e09eSopenharmony_ci } 446855e09eSopenharmony_ci } 456855e09eSopenharmony_ci} 466855e09eSopenharmony_ci 476855e09eSopenharmony_ciimpl Debug for Expr { 486855e09eSopenharmony_ci fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result { 496855e09eSopenharmony_ci use self::Expr::*; 506855e09eSopenharmony_ci match *self { 516855e09eSopenharmony_ci Value(val) => write!(format, "{}", val), 526855e09eSopenharmony_ci Add(ref left, ref right) => write!(format, "({:?} + {:?})", left, right), 536855e09eSopenharmony_ci Sub(ref left, ref right) => write!(format, "({:?} - {:?})", left, right), 546855e09eSopenharmony_ci Mul(ref left, ref right) => write!(format, "({:?} * {:?})", left, right), 556855e09eSopenharmony_ci Div(ref left, ref right) => write!(format, "({:?} / {:?})", left, right), 566855e09eSopenharmony_ci Paren(ref expr) => write!(format, "[{:?}]", expr), 576855e09eSopenharmony_ci } 586855e09eSopenharmony_ci } 596855e09eSopenharmony_ci} 606855e09eSopenharmony_ci 616855e09eSopenharmony_cifn parens(i: &str) -> IResult<&str, Expr> { 626855e09eSopenharmony_ci delimited( 636855e09eSopenharmony_ci multispace, 646855e09eSopenharmony_ci delimited(tag("("), map(expr, |e| Expr::Paren(Box::new(e))), tag(")")), 656855e09eSopenharmony_ci multispace, 666855e09eSopenharmony_ci )(i) 676855e09eSopenharmony_ci} 686855e09eSopenharmony_ci 696855e09eSopenharmony_cifn factor(i: &str) -> IResult<&str, Expr> { 706855e09eSopenharmony_ci alt(( 716855e09eSopenharmony_ci map( 726855e09eSopenharmony_ci map_res(delimited(multispace, digit, multispace), FromStr::from_str), 736855e09eSopenharmony_ci Expr::Value, 746855e09eSopenharmony_ci ), 756855e09eSopenharmony_ci parens, 766855e09eSopenharmony_ci ))(i) 776855e09eSopenharmony_ci} 786855e09eSopenharmony_ci 796855e09eSopenharmony_cifn fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr { 806855e09eSopenharmony_ci remainder.into_iter().fold(initial, |acc, pair| { 816855e09eSopenharmony_ci let (oper, expr) = pair; 826855e09eSopenharmony_ci match oper { 836855e09eSopenharmony_ci Oper::Add => Expr::Add(Box::new(acc), Box::new(expr)), 846855e09eSopenharmony_ci Oper::Sub => Expr::Sub(Box::new(acc), Box::new(expr)), 856855e09eSopenharmony_ci Oper::Mul => Expr::Mul(Box::new(acc), Box::new(expr)), 866855e09eSopenharmony_ci Oper::Div => Expr::Div(Box::new(acc), Box::new(expr)), 876855e09eSopenharmony_ci } 886855e09eSopenharmony_ci }) 896855e09eSopenharmony_ci} 906855e09eSopenharmony_ci 916855e09eSopenharmony_cifn term(i: &str) -> IResult<&str, Expr> { 926855e09eSopenharmony_ci let (i, initial) = factor(i)?; 936855e09eSopenharmony_ci let (i, remainder) = many0(alt(( 946855e09eSopenharmony_ci |i| { 956855e09eSopenharmony_ci let (i, mul) = preceded(tag("*"), factor)(i)?; 966855e09eSopenharmony_ci Ok((i, (Oper::Mul, mul))) 976855e09eSopenharmony_ci }, 986855e09eSopenharmony_ci |i| { 996855e09eSopenharmony_ci let (i, div) = preceded(tag("/"), factor)(i)?; 1006855e09eSopenharmony_ci Ok((i, (Oper::Div, div))) 1016855e09eSopenharmony_ci }, 1026855e09eSopenharmony_ci )))(i)?; 1036855e09eSopenharmony_ci 1046855e09eSopenharmony_ci Ok((i, fold_exprs(initial, remainder))) 1056855e09eSopenharmony_ci} 1066855e09eSopenharmony_ci 1076855e09eSopenharmony_cifn expr(i: &str) -> IResult<&str, Expr> { 1086855e09eSopenharmony_ci let (i, initial) = term(i)?; 1096855e09eSopenharmony_ci let (i, remainder) = many0(alt(( 1106855e09eSopenharmony_ci |i| { 1116855e09eSopenharmony_ci let (i, add) = preceded(tag("+"), term)(i)?; 1126855e09eSopenharmony_ci Ok((i, (Oper::Add, add))) 1136855e09eSopenharmony_ci }, 1146855e09eSopenharmony_ci |i| { 1156855e09eSopenharmony_ci let (i, sub) = preceded(tag("-"), term)(i)?; 1166855e09eSopenharmony_ci Ok((i, (Oper::Sub, sub))) 1176855e09eSopenharmony_ci }, 1186855e09eSopenharmony_ci )))(i)?; 1196855e09eSopenharmony_ci 1206855e09eSopenharmony_ci Ok((i, fold_exprs(initial, remainder))) 1216855e09eSopenharmony_ci} 1226855e09eSopenharmony_ci 1236855e09eSopenharmony_ci#[test] 1246855e09eSopenharmony_cifn factor_test() { 1256855e09eSopenharmony_ci assert_eq!( 1266855e09eSopenharmony_ci factor(" 3 ").map(|(i, x)| (i, format!("{:?}", x))), 1276855e09eSopenharmony_ci Ok(("", String::from("3"))) 1286855e09eSopenharmony_ci ); 1296855e09eSopenharmony_ci} 1306855e09eSopenharmony_ci 1316855e09eSopenharmony_ci#[test] 1326855e09eSopenharmony_cifn term_test() { 1336855e09eSopenharmony_ci assert_eq!( 1346855e09eSopenharmony_ci term(" 3 * 5 ").map(|(i, x)| (i, format!("{:?}", x))), 1356855e09eSopenharmony_ci Ok(("", String::from("(3 * 5)"))) 1366855e09eSopenharmony_ci ); 1376855e09eSopenharmony_ci} 1386855e09eSopenharmony_ci 1396855e09eSopenharmony_ci#[test] 1406855e09eSopenharmony_cifn expr_test() { 1416855e09eSopenharmony_ci assert_eq!( 1426855e09eSopenharmony_ci expr(" 1 + 2 * 3 ").map(|(i, x)| (i, format!("{:?}", x))), 1436855e09eSopenharmony_ci Ok(("", String::from("(1 + (2 * 3))"))) 1446855e09eSopenharmony_ci ); 1456855e09eSopenharmony_ci assert_eq!( 1466855e09eSopenharmony_ci expr(" 1 + 2 * 3 / 4 - 5 ").map(|(i, x)| (i, format!("{:?}", x))), 1476855e09eSopenharmony_ci Ok(("", String::from("((1 + ((2 * 3) / 4)) - 5)"))) 1486855e09eSopenharmony_ci ); 1496855e09eSopenharmony_ci assert_eq!( 1506855e09eSopenharmony_ci expr(" 72 / 2 / 3 ").map(|(i, x)| (i, format!("{:?}", x))), 1516855e09eSopenharmony_ci Ok(("", String::from("((72 / 2) / 3)"))) 1526855e09eSopenharmony_ci ); 1536855e09eSopenharmony_ci} 1546855e09eSopenharmony_ci 1556855e09eSopenharmony_ci#[test] 1566855e09eSopenharmony_cifn parens_test() { 1576855e09eSopenharmony_ci assert_eq!( 1586855e09eSopenharmony_ci expr(" ( 1 + 2 ) * 3 ").map(|(i, x)| (i, format!("{:?}", x))), 1596855e09eSopenharmony_ci Ok(("", String::from("([(1 + 2)] * 3)"))) 1606855e09eSopenharmony_ci ); 1616855e09eSopenharmony_ci} 162