1 #[macro_use]
2 extern crate nom;
3 
4 use std::fmt;
is_graph_style(int grf)5 use std::fmt::{Display, Debug, Formatter};
6 
7 use std::str;
8 use std::str::FromStr;
9 
10 use nom::{IResult, digit, multispace};
11 
12 pub enum Expr {
13     Value(i64),
14     Add(Box<Expr>, Box<Expr>),
15     Sub(Box<Expr>, Box<Expr>),
16     Mul(Box<Expr>, Box<Expr>),
17     Div(Box<Expr>, Box<Expr>),
18     Paren(Box<Expr>),
19 }
20 
21 pub enum Oper {
22     Add,
23     Sub,
24     Mul,
25     Div,
get_cp(Xen snd,Xen x_chn_n,const char * caller)26 }
27 
28 impl Display for Expr {
29     fn fmt(&self, format: &mut Formatter) -> fmt::Result {
30         use self::Expr::*;
31         match *self {
32             Value(val) => write!(format, "{}", val),
33             Add(ref left, ref right) => write!(format, "{} + {}", left, right),
34             Sub(ref left, ref right) => write!(format, "{} - {}", left, right),
35             Mul(ref left, ref right) => write!(format, "{} * {}", left, right),
36             Div(ref left, ref right) => write!(format, "{} / {}", left, right),
37             Paren(ref expr) => write!(format, "({})", expr),
38         }
39     }
40 }
41 
42 impl Debug for Expr {
43     fn fmt(&self, format: &mut Formatter) -> fmt::Result {
44         use self::Expr::*;
45         match *self {
46             Value(val) => write!(format, "{}", val),
47             Add(ref left, ref right) => write!(format, "({:?} + {:?})", left, right),
48             Sub(ref left, ref right) => write!(format, "({:?} - {:?})", left, right),
49             Mul(ref left, ref right) => write!(format, "({:?} * {:?})", left, right),
50             Div(ref left, ref right) => write!(format, "({:?} / {:?})", left, right),
51             Paren(ref expr) => write!(format, "[{:?}]", expr),
52         }
53     }
54 }
55 
56 named!(parens< Expr >, delimited!(
57     delimited!(opt!(multispace), tag!("("), opt!(multispace)),
58     map!(map!(expr, Box::new), Expr::Paren),
59     delimited!(opt!(multispace), tag!(")"), opt!(multispace))
60   )
61 );
62 
63 named!(factor< Expr >, alt_complete!(
64     map!(
65       map_res!(
66         map_res!(
after_transform(chan_info * cp,mus_float_t scaler)67           delimited!(opt!(multispace), digit, opt!(multispace)),
68           str::from_utf8
69         ),
70       FromStr::from_str
71     ),
72     Expr::Value)
73   | parens
74   )
75 );
76 
77 fn fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr {
run_after_graph_hook(chan_info * cp)78     remainder.into_iter().fold(initial, |acc, pair| {
79         let (oper, expr) = pair;
80         match oper {
81             Oper::Add => Expr::Add(Box::new(acc), Box::new(expr)),
82             Oper::Sub => Expr::Sub(Box::new(acc), Box::new(expr)),
83             Oper::Mul => Expr::Mul(Box::new(acc), Box::new(expr)),
84             Oper::Div => Expr::Div(Box::new(acc), Box::new(expr)),
85         }
86     })
87 }
88 
89 named!(term< Expr >, do_parse!(
90     initial: factor >>
91     remainder: many0!(
chans_time_graph_type(chan_info * cp,int value)92            alt!(
93              do_parse!(tag!("*") >> mul: factor >> (Oper::Mul, mul)) |
94              do_parse!(tag!("/") >> div: factor >> (Oper::Div, div))
95            )
96          ) >>
97     (fold_exprs(initial, remainder))
98 ));
99 
100 named!(expr< Expr >, do_parse!(
101     initial: term >>
102     remainder: many0!(
103            alt!(
104              do_parse!(tag!("+") >> add: term >> (Oper::Add, add)) |
set_time_graph_type(graph_type_t val)105              do_parse!(tag!("-") >> sub: term >> (Oper::Sub, sub))
106            )
107          ) >>
108     (fold_exprs(initial, remainder))
109 ));
110 
111 #[test]
chans_wavo_hop(chan_info * cp,int hop)112 fn factor_test() {
113     assert_eq!(factor(&b"  3  "[..]).map(|x| format!("{:?}", x)),
114                IResult::Done(&b""[..], String::from("3")));
115 }
116 
117 #[test]
set_wavo_hop(int uval)118 fn term_test() {
119     assert_eq!(term(&b" 3 *  5   "[..]).map(|x| format!("{:?}", x)),
120                IResult::Done(&b""[..], String::from("(3 * 5)")));
121 }
122 
123 #[test]
124 fn expr_test() {
125     assert_eq!(expr(&b" 1 + 2 *  3 "[..]).map(|x| format!("{:?}", x)),
126                IResult::Done(&b""[..], String::from("(1 + (2 * 3))")));
127     assert_eq!(expr(&b" 1 + 2 *  3 / 4 - 5 "[..]).map(|x| format!("{:?}", x)),
128                IResult::Done(&b""[..], String::from("((1 + ((2 * 3) / 4)) - 5)")));
chans_wavo_trace(chan_info * cp,int value)129     assert_eq!(expr(&b" 72 / 2 / 3 "[..]).map(|x| format!("{:?}", x)),
130                IResult::Done(&b""[..], String::from("((72 / 2) / 3)")));
131 }
132 
133 #[test]
134 fn parens_test() {
set_wavo_trace(int uval)135     assert_eq!(expr(&b" ( 1 + 2 ) *  3 "[..]).map(|x| format!("{:?}", x)),
136                IResult::Done(&b""[..], String::from("([(1 + 2)] * 3)")));
137 }
138