mirror of
https://gitee.com/openharmony/third_party_rust_nom
synced 2024-11-27 17:51:02 +00:00
6a15807cd4
this will make it easier to be compatible with other crates like error_chain, and we can reuse a lot of code coming for free with Result. Incomplete is merged into the error side. I still do not consider it to be an error,but this side will also contain unrecoverable errors at some point (errors that cause alt and others to return instead of testing the next branch), so it will be easier to put it in this enum.
88 lines
2.2 KiB
Rust
88 lines
2.2 KiB
Rust
#[macro_use]
|
|
extern crate nom;
|
|
|
|
use nom::{IResult,digit};
|
|
|
|
// Parser definition
|
|
|
|
use std::str;
|
|
use std::str::FromStr;
|
|
|
|
// We parse any expr surrounded by parens, ignoring all whitespaces around those
|
|
named!(parens<i64>, ws!(delimited!( tag!("("), expr, tag!(")") )) );
|
|
|
|
// We transform an integer string into a i64, ignoring surrounding whitespaces
|
|
// We look for a digit suite, and try to convert it.
|
|
// If either str::from_utf8 or FromStr::from_str fail,
|
|
// we fallback to the parens parser defined above
|
|
named!(factor<i64>, alt!(
|
|
map_res!(
|
|
map_res!(
|
|
ws!(digit),
|
|
str::from_utf8
|
|
),
|
|
FromStr::from_str
|
|
)
|
|
| parens
|
|
)
|
|
);
|
|
|
|
// We read an initial factor and for each time we find
|
|
// a * or / operator followed by another factor, we do
|
|
// the math by folding everything
|
|
named!(term <i64>, do_parse!(
|
|
init: factor >>
|
|
res: fold_many0!(
|
|
pair!(alt!(tag!("*") | tag!("/")), factor),
|
|
init,
|
|
|acc, (op, val): (&[u8], i64)| {
|
|
if (op[0] as char) == '*' { acc * val } else { acc / val }
|
|
}
|
|
) >>
|
|
(res)
|
|
)
|
|
);
|
|
|
|
named!(expr <i64>, do_parse!(
|
|
init: term >>
|
|
res: fold_many0!(
|
|
pair!(alt!(tag!("+") | tag!("-")), term),
|
|
init,
|
|
|acc, (op, val): (&[u8], i64)| {
|
|
if (op[0] as char) == '+' { acc + val } else { acc - val }
|
|
}
|
|
) >>
|
|
(res)
|
|
)
|
|
);
|
|
|
|
#[test]
|
|
fn factor_test() {
|
|
assert_eq!(factor(&b"3"[..]), Ok((&b""[..], 3)));
|
|
assert_eq!(factor(&b" 12"[..]), Ok((&b""[..], 12)));
|
|
assert_eq!(factor(&b"537 "[..]), Ok((&b""[..], 537)));
|
|
assert_eq!(factor(&b" 24 "[..]), Ok((&b""[..], 24)));
|
|
}
|
|
|
|
|
|
#[test]
|
|
fn term_test() {
|
|
assert_eq!(term(&b" 12 *2 / 3"[..]), Ok((&b""[..], 8)));
|
|
assert_eq!(term(&b" 2* 3 *2 *2 / 3"[..]), Ok((&b""[..], 8)));
|
|
assert_eq!(term(&b" 48 / 3/2"[..]), Ok((&b""[..], 8)));
|
|
}
|
|
|
|
#[test]
|
|
fn expr_test() {
|
|
assert_eq!(expr(&b" 1 + 2 "[..]), Ok((&b""[..], 3)));
|
|
assert_eq!(expr(&b" 12 + 6 - 4+ 3"[..]), Ok((&b""[..], 17)));
|
|
assert_eq!(expr(&b" 1 + 2*3 + 4"[..]), Ok((&b""[..], 11)));
|
|
}
|
|
|
|
#[test]
|
|
fn parens_test() {
|
|
assert_eq!(expr(&b" ( 2 )"[..]), Ok((&b""[..], 2)));
|
|
assert_eq!(expr(&b" 2* ( 3 + 4 ) "[..]), Ok((&b""[..], 14)));
|
|
assert_eq!(expr(&b" 2*2 / ( 5 - 1) + 3"[..]), Ok((&b""[..], 4)));
|
|
}
|