1use std::str;
17
18use ast::ASTNode;
19use ast::ASTNode::*;
20use super::exp::parse_exp;
21use super::number::parse_number;
22
23named!(pub parse_op<ASTNode>, map!(parse_exponent, |a|a));
26
27named!(parse_unop<ASTNode>, do_parse!(
28 unop: many0!(unop)
29 >> right: parse_binop
30 >> (fold_unop(unop, right))));
31
32named!(parse_binop<ASTNode>, do_parse!(
33 left: parse_atom
34 >> right: many0!(do_parse!(bop: binop >> right: parse_atom >> (bop, right)))
35 >> (fold_binop(left, right))));
36
37named!(parse_exponent<ASTNode>, do_parse!(
38 left: parse_unop
39 >> right: many0!(do_parse!(xp: exponent >> right: parse_unop >> (xp, right)))
40 >> (fold_binop(left, right))));
41
42named!(parse_atom<ASTNode>, alt!(parse_number | delimited!(tag!("("), ws!(parse_exp), tag!(")"))));
43
44named!(exponent<BinOp>, map!(ws!(tag!("^")), |_| BinOp::Exp));
45
46named!(binop<BinOp>, alt!(
47 ws!(tag!("*")) => { |_| BinOp::Mul } |
48 ws!(tag!("/")) => { |_| BinOp::Div } |
49 ws!(tag!("//")) => { |_| BinOp::FDiv } |
50 ws!(tag!("%")) => { |_| BinOp::Mod } |
51 ws!(tag!("+")) => { |_| BinOp::Add } |
52 ws!(tag!("-")) => { |_| BinOp::Sub } |
53 ws!(tag!("..")) => { |_| BinOp::Concat } |
54 ws!(tag!("<<")) => { |_| BinOp::Lsh } |
55 ws!(tag!(">>")) => { |_| BinOp::Rsh } |
56 ws!(tag!("&")) => { |_| BinOp::BitAnd } |
57 ws!(tag!("~")) => { |_| BinOp::BitXor } |
58 ws!(tag!("|")) => { |_| BinOp::BitOr } |
59 ws!(tag!("<")) => { |_| BinOp::Lt } |
60 ws!(tag!(">")) => { |_| BinOp::Gt } |
61 ws!(tag!("<=")) => { |_| BinOp::Le } |
62 ws!(tag!(">=")) => { |_| BinOp::Ge } |
63 ws!(tag!("~=")) => { |_| BinOp::Ne } |
64 ws!(tag!("==")) => { |_| BinOp::Eq } |
65 ws!(tag!("and")) => { |_| BinOp::And } |
66 ws!(tag!("or")) => { |_| BinOp::Or }
67));
68
69#[derive(Debug)]
70pub enum BinOp {
71 Exp,
72 Mul,
73 Div,
74 FDiv,
75 Mod,
76 Add,
77 Sub,
78 Concat,
79 Lsh,
80 Rsh,
81 BitAnd,
82 BitXor,
83 BitOr,
84 Lt,
85 Gt,
86 Le,
87 Ge,
88 Ne,
89 Eq,
90 And,
91 Or,
92}
93
94
95fn fold_unop(unop: Vec<UnOp>, initial: ASTNode) -> ASTNode {
96 unop.into_iter().fold(initial, |acc, op| {
97 println!("Proc unop: {:?}", op);
98 match op {
99 UnOp::BinNot => astb!(BinNot, acc),
100 UnOp::Not => astb!(Not, acc),
101 UnOp::Len => astb!(Len, acc),
102 UnOp::UMin => astb!(UMin, acc),
103 }
104 })
105}
106
107fn fold_binop(left: ASTNode, remainder: Vec<(BinOp, ASTNode)>) -> ASTNode {
108 remainder.into_iter().fold(left, |acc, pair| {
109 let (op, right) = pair;
110 println!("Proc binop: {:?}", op);
111 match op {
112 BinOp::Exp => astb!(Exp, acc, right),
114 BinOp::Mul => astb!(Mul, acc, right),
115 BinOp::Div => astb!(Div, acc, right),
116 BinOp::FDiv => astb!(FDiv, acc, right),
117 BinOp::Mod => astb!(Mod, acc, right),
118 BinOp::Add => astb!(Add, acc, right),
119 BinOp::Sub => astb!(Sub, acc, right),
120 BinOp::Concat => astb!(Concat, acc, right),
122 BinOp::Lsh => astb!(Lsh, acc, right),
123 BinOp::Rsh => astb!(Rsh, acc, right),
124 BinOp::BitAnd => astb!(BitAnd, acc, right),
125 BinOp::BitXor => astb!(BitXor, acc, right),
126 BinOp::BitOr => astb!(BitOr, acc, right),
127 BinOp::Lt => astb!(Lt, acc, right),
128 BinOp::Gt => astb!(Gt, acc, right),
129 BinOp::Le => astb!(Le, acc, right),
130 BinOp::Ge => astb!(Ge, acc, right),
131 BinOp::Ne => astb!(Ne, acc, right),
132 BinOp::Eq => astb!(Eq, acc, right),
133 BinOp::And => astb!(And, acc, right),
134 BinOp::Or => astb!(Or, acc, right),
135 }
136 })
137}
138
139
140named!(pub unop<UnOp>, alt!(
142 ws!(tag!("not")) => { |_| UnOp::Not } |
143 ws!(tag!("#")) => { |_| UnOp::Len } |
144 ws!(tag!("-")) => { |_| UnOp::UMin } |
145 ws!(tag!("~")) => { |_| UnOp::BinNot }
146));
147
148#[derive(Debug)]
149pub enum UnOp {
150 Not,
151 Len,
152 UMin,
153 BinNot,
154}