nom_lua/
op.rs

1// Copyright 2017 The nom-lua project developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//mod relational_ops;
10//mod arithmetic_ops;
11//mod binary_ops;
12//mod unary_ops;
13//mod logic_ops;
14//mod concat_ops;
15
16use std::str;
17
18use ast::ASTNode;
19use ast::ASTNode::*;
20use super::exp::parse_exp;
21use super::number::parse_number;
22
23//named!(pub parse_op<ASTNode>, dbg_dmp!(alt!(parse_exponent | parse_unop | parse_binop)));
24// for some reason we have to use the map
25named!(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            //TODO: This is right Associative, we need to invert this operation
113            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            //TODO: This is right Associative, we need to invert this operation
121            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
140// TODO: Change to be just preceded by whitespace
141named!(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}