nom_operator/
macros.rs

1// Copyright 2017 The nom-operator 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
9macro_rules! testcase {
10    ($name: ident, $input: expr, $res: expr) => {
11        #[test]
12        fn $name() {
13            let mut opp = opparser_factory();
14            assert_eq!(
15                opp.parse($input),
16                IResult::Done("".as_bytes(), $res)
17            );
18        }
19    }
20}
21
22// Test macro
23macro_rules! t {
24    ($left: expr, $op: expr, $right: expr) => {
25        $crate::Expr::BinExpr {
26            left: Box::new($left),
27            op: $op,
28            right: Box::new($right),
29        }
30    };
31    ($op: expr, $left: expr) => {
32        $crate::Expr::UnExpr {
33            item: Box::new($left),
34            op: $op,
35        }
36    };
37    ($a: expr) => {
38        $crate::Expr::Atom(format!("{}", $a).as_bytes())
39    };
40}
41
42// TODO: Tests for this macro
43/// Matches a token and returns an operator with info
44#[macro_export]
45#[doc(hidden)]
46macro_rules! alt_operator {
47    (__impl $i:expr,
48            $op_path: path,
49            $token: path,
50            $assoc: expr,
51            $prec: expr => $($rest:tt)* ) => (
52
53        alt_operator!(__impl $i, $op_path, call!($token), $assoc, $prec => $($rest)*);
54
55    );
56
57    (__impl $i:expr,
58            $op_path: path,
59            $token: ident!( $($token_args:tt)* ),
60            $assoc: expr,
61            $prec: expr => $($rest:tt)*) => (
62
63        match $token!( $i, $($token_args)* ) {
64            $crate::IResult::Error(_)      => {
65                alt_operator!(__impl $i, $($rest)* )
66            },
67            $crate::IResult::Incomplete(x) => $crate::IResult::Incomplete(x),
68            $crate::IResult::Done(i, _)     => {
69                $crate::IResult::Done(i, OperatorInfo {
70                    op: $op_path,
71                    associativity: $assoc,
72                    precedence: $prec,
73                })
74            }
75        }
76
77    );
78
79    (__impl $i:expr,
80            $op_path: path,
81            $token: path,
82            $assoc: expr,
83            $prec: expr) => (
84
85        alt_operator!(__impl $i, $op_path, call!($token), $assoc, $prec, $($rest)*);
86
87    );
88
89
90    (__impl $i:expr,
91            $op_path: path,
92            $token: ident!( $($token_args:tt)* ),
93            $assoc: expr,
94            $prec: expr) => (
95
96        match $token!( $i, $($token_args)* ) {
97            $crate::IResult::Error(e)      => $crate::IResult::Error(e),
98            $crate::IResult::Incomplete(x) => $crate::IResult::Incomplete(x),
99            $crate::IResult::Done(i, _)     => {
100                $crate::IResult::Done(i, OperatorInfo {
101                    op: $op_path,
102                    associativity: $assoc,
103                    precedence: $prec,
104                })
105            }
106        }
107
108    );
109
110    ($i:expr, $($rest:tt)*) => (
111        {
112            alt_operator!(__impl $i, $($rest)*)
113        }
114    );
115}
116
117/// Extract a result from a sucessful parse
118/// return Incomplete or Error otherwise
119#[macro_export]
120#[doc(hidden)]
121macro_rules! extract_result {
122    ( $($input:tt)* ) => {
123        match $($input)* {
124            $crate::IResult::Incomplete(x) => {
125                return $crate::IResult::Incomplete(x);
126            },
127            $crate::IResult::Error(e) => {
128                return $crate::IResult::Error(e);
129            },
130            $crate::IResult::Done(i, o) => (i, o),
131        }
132    }
133}
134
135/// Parses an input expression according to the operators defined in the
136/// arguments
137#[macro_export]
138macro_rules! parse_operator {
139    (__impl
140     $i: expr,
141     // TODO: the final macro ideally wouldn't require type info
142     <$ty: ty, $op_ty: ty>,
143     $atom: path,
144     $($ops:tt)*) => {
145        parse_operator!(__impl $i, <$ty, $op_ty>, call!($atom), $($ops)*)
146    };
147
148    (__impl
149     $i: expr,
150     // TODO: the final macro ideally wouldn't require type info
151     <$ty: ty, $op_ty: ty>,
152     $atom: ident!( $($atom_args:tt)* ),
153     $($ops:tt)*) => {{
154       use $crate::Expr;
155       use OperatorInfo;
156       fn recurse(i: &[u8], min_prec: u32) ->
157           $crate::IResult<&[u8], Expr<$ty, $op_ty>> {
158       }
159       recurse($i, 0)
160    }};
161
162    ($i: expr, <$ty: ty, $op_ty: ty>, $($rest:tt)* ) => {
163        parse_operator!(__impl $i, <$ty, $op_ty>, $($rest)*)
164    }
165}
166