Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
mod parser;
mod parser_ast;
mod parser_lexer;
use winnow::prelude::*;
#[allow(clippy::eq_op, clippy::erasing_op)]
fn arithmetic(c: &mut criterion::Criterion) {
let data = " 2*2 / ( 5 - 1) + 3 / 4 * (2 - 7 + 567 *12 /2) + 3*(1+2*( 45 /2))";
let expected = 2 * 2 / (5 - 1) + 3 * (1 + 2 * (45 / 2));
assert_eq!(parser::expr.parse(data), Ok(expected));
assert_eq!(
parser_ast::expr.parse(data).map(|ast| ast.eval()),
Ok(expected)
);
assert_eq!(
parser_lexer::expr2.parse(data).map(|ast| ast.eval()),
Ok(expected)
);
c.bench_function("direct", |b| {
b.iter(|| parser::expr.parse(data).unwrap());
});
c.bench_function("ast", |b| {
b.iter(|| parser_ast::expr.parse(data).unwrap().eval());
});
c.bench_function("lexer", |b| {
b.iter(|| parser_lexer::expr2.parse_peek(data).unwrap());
});
}
criterion::criterion_group!(benches, arithmetic);
criterion::criterion_main!(benches);

View File

@@ -0,0 +1,93 @@
use winnow::prelude::*;
mod parser;
mod parser_ast;
mod parser_lexer;
#[cfg(test)]
mod test_parser;
#[cfg(test)]
mod test_parser_ast;
#[cfg(test)]
mod test_parser_lexer;
fn main() -> Result<(), lexopt::Error> {
let args = Args::parse()?;
let input = args.input.as_deref().unwrap_or("1 + 1");
if let Err(err) = calc(input, args.implementation) {
println!("FAILED");
println!("{err}");
}
Ok(())
}
fn calc(
input: &str,
imp: Impl,
) -> Result<(), winnow::error::ParseError<&str, winnow::error::ContextError>> {
println!("{input} =");
match imp {
Impl::Eval => {
let result = parser::expr.parse(input)?;
println!(" {result}");
}
Impl::Ast => {
let result = parser_ast::expr.parse(input)?;
println!(" {:#?}={}", result, result.eval());
}
Impl::Lexer => {
let tokens = parser_lexer::tokens.parse(input)?;
println!(" {tokens:#?}");
let tokens = parser_lexer::Tokens::new(&tokens);
let result = parser_lexer::expr.parse(tokens).unwrap();
println!(" {:#?}={}", result, result.eval());
}
}
Ok(())
}
#[derive(Default)]
struct Args {
input: Option<String>,
implementation: Impl,
}
enum Impl {
Eval,
Ast,
Lexer,
}
impl Default for Impl {
fn default() -> Self {
Self::Eval
}
}
impl Args {
fn parse() -> Result<Self, lexopt::Error> {
use lexopt::prelude::*;
let mut res = Args::default();
let mut args = lexopt::Parser::from_env();
while let Some(arg) = args.next()? {
match arg {
Long("impl") => {
res.implementation = args.value()?.parse_with(|s| match s {
"eval" => Ok(Impl::Eval),
"ast" => Ok(Impl::Ast),
"lexer" => Ok(Impl::Lexer),
_ => Err("expected `eval`, `ast`"),
})?;
}
Value(input) => {
res.input = Some(input.string()?);
}
_ => return Err(arg.unexpected()),
}
}
Ok(res)
}
}

View File

@@ -0,0 +1,68 @@
use std::str::FromStr;
use winnow::prelude::*;
use winnow::Result;
use winnow::{
ascii::{digit1 as digits, multispace0 as multispaces},
combinator::alt,
combinator::delimited,
combinator::repeat,
token::one_of,
};
// Parser definition
pub(crate) fn expr(i: &mut &str) -> Result<i64> {
let init = term.parse_next(i)?;
repeat(0.., (one_of(['+', '-']), term))
.fold(
move || init,
|acc, (op, val): (char, i64)| {
if op == '+' {
acc + val
} else {
acc - val
}
},
)
.parse_next(i)
}
// 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
pub(crate) fn term(i: &mut &str) -> Result<i64> {
let init = factor.parse_next(i)?;
repeat(0.., (one_of(['*', '/']), factor))
.fold(
move || init,
|acc, (op, val): (char, i64)| {
if op == '*' {
acc * val
} else {
acc / val
}
},
)
.parse_next(i)
}
// We transform an integer string into a i64, ignoring surrounding whitespace
// 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
pub(crate) fn factor(i: &mut &str) -> Result<i64> {
delimited(
multispaces,
alt((digits.try_map(FromStr::from_str), parens)),
multispaces,
)
.parse_next(i)
}
// We parse any expr surrounded by parens, ignoring all whitespace around those
fn parens(i: &mut &str) -> Result<i64> {
delimited('(', expr, ')').parse_next(i)
}

View File

@@ -0,0 +1,100 @@
use std::fmt;
use std::fmt::{Debug, Display, Formatter};
use std::str::FromStr;
use winnow::prelude::*;
use winnow::Result;
use winnow::{
ascii::{digit1 as digits, multispace0 as multispaces},
combinator::alt,
combinator::delimited,
combinator::repeat,
token::one_of,
};
#[derive(Debug, Clone)]
pub(crate) enum Expr {
Value(i64),
Add(Box<Expr>, Box<Expr>),
Sub(Box<Expr>, Box<Expr>),
Mul(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>),
Paren(Box<Expr>),
}
impl Expr {
pub(crate) fn eval(&self) -> i64 {
match self {
Self::Value(v) => *v,
Self::Add(lhs, rhs) => lhs.eval() + rhs.eval(),
Self::Sub(lhs, rhs) => lhs.eval() - rhs.eval(),
Self::Mul(lhs, rhs) => lhs.eval() * rhs.eval(),
Self::Div(lhs, rhs) => lhs.eval() / rhs.eval(),
Self::Paren(expr) => expr.eval(),
}
}
}
impl Display for Expr {
fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result {
use Expr::{Add, Div, Mul, Paren, Sub, Value};
match *self {
Value(val) => write!(format, "{val}"),
Add(ref left, ref right) => write!(format, "{left} + {right}"),
Sub(ref left, ref right) => write!(format, "{left} - {right}"),
Mul(ref left, ref right) => write!(format, "{left} * {right}"),
Div(ref left, ref right) => write!(format, "{left} / {right}"),
Paren(ref expr) => write!(format, "({expr})"),
}
}
}
pub(crate) fn expr(i: &mut &str) -> Result<Expr> {
let init = term.parse_next(i)?;
repeat(0.., (one_of(['+', '-']), term))
.fold(
move || init.clone(),
|acc, (op, val): (char, Expr)| {
if op == '+' {
Expr::Add(Box::new(acc), Box::new(val))
} else {
Expr::Sub(Box::new(acc), Box::new(val))
}
},
)
.parse_next(i)
}
pub(crate) fn term(i: &mut &str) -> Result<Expr> {
let init = factor.parse_next(i)?;
repeat(0.., (one_of(['*', '/']), factor))
.fold(
move || init.clone(),
|acc, (op, val): (char, Expr)| {
if op == '*' {
Expr::Mul(Box::new(acc), Box::new(val))
} else {
Expr::Div(Box::new(acc), Box::new(val))
}
},
)
.parse_next(i)
}
pub(crate) fn factor(i: &mut &str) -> Result<Expr> {
delimited(
multispaces,
alt((digits.try_map(FromStr::from_str).map(Expr::Value), parens)),
multispaces,
)
.parse_next(i)
}
fn parens(i: &mut &str) -> Result<Expr> {
delimited("(", expr, ")")
.map(|e| Expr::Paren(Box::new(e)))
.parse_next(i)
}

View File

@@ -0,0 +1,246 @@
use std::fmt;
use std::fmt::{Debug, Display, Formatter};
use winnow::prelude::*;
use winnow::Result;
use winnow::{
ascii::{digit1 as digits, multispace0 as multispaces},
combinator::alt,
combinator::dispatch,
combinator::eof,
combinator::fail,
combinator::opt,
combinator::peek,
combinator::repeat,
combinator::{delimited, preceded, terminated},
error::ContextError,
stream::TokenSlice,
token::any,
token::literal,
token::one_of,
token::take_till,
};
/// Lex and parse
#[allow(dead_code)]
pub(crate) fn expr2(i: &mut &str) -> Result<Expr> {
let tokens = tokens.parse_next(i)?;
let mut tokens = Tokens::new(&tokens);
expr.parse_next(&mut tokens)
}
#[derive(Clone, PartialEq, Eq)]
pub(crate) struct Token<'s> {
kind: TokenKind,
raw: &'s str,
}
impl fmt::Debug for Token<'_> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
// Customized for brevity for a better `winnow/debug` experience
match self.kind {
TokenKind::Value => Debug::fmt(self.raw, fmt),
TokenKind::Oper(oper) => Debug::fmt(&oper, fmt),
TokenKind::OpenParen => fmt.write_str("OpenParen"),
TokenKind::CloseParen => fmt.write_str("CloseParen"),
TokenKind::Unknown => fmt.write_str("Unknown"),
TokenKind::Eof => fmt.write_str("Eof"),
}
}
}
impl PartialEq<TokenKind> for Token<'_> {
fn eq(&self, other: &TokenKind) -> bool {
self.kind == *other
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum TokenKind {
Value,
Oper(Oper),
OpenParen,
CloseParen,
Unknown,
Eof,
}
impl<'i> Parser<Tokens<'i>, &'i Token<'i>, ContextError> for TokenKind {
fn parse_next(&mut self, input: &mut Tokens<'i>) -> Result<&'i Token<'i>> {
literal(*self).parse_next(input).map(|t| &t[0])
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum Oper {
Add,
Sub,
Mul,
Div,
}
impl winnow::stream::ContainsToken<&'_ Token<'_>> for TokenKind {
#[inline(always)]
fn contains_token(&self, token: &'_ Token<'_>) -> bool {
*self == token.kind
}
}
impl winnow::stream::ContainsToken<&'_ Token<'_>> for &'_ [TokenKind] {
#[inline]
fn contains_token(&self, token: &'_ Token<'_>) -> bool {
self.iter().any(|t| *t == token.kind)
}
}
impl<const LEN: usize> winnow::stream::ContainsToken<&'_ Token<'_>> for &'_ [TokenKind; LEN] {
#[inline]
fn contains_token(&self, token: &'_ Token<'_>) -> bool {
self.iter().any(|t| *t == token.kind)
}
}
impl<const LEN: usize> winnow::stream::ContainsToken<&'_ Token<'_>> for [TokenKind; LEN] {
#[inline]
fn contains_token(&self, token: &'_ Token<'_>) -> bool {
self.iter().any(|t| *t == token.kind)
}
}
/// Lex tokens
///
/// See [`expr`] to parse the tokens
pub(crate) fn tokens<'s>(i: &mut &'s str) -> Result<Vec<Token<'s>>> {
let mut tokens: Vec<_> =
preceded(multispaces, repeat(1.., terminated(token, multispaces))).parse_next(i)?;
if let Some(eof) = opt(eof.map(|raw| Token {
kind: TokenKind::Eof,
raw,
}))
.parse_next(i)?
{
tokens.push(eof);
}
Ok(tokens)
}
fn token<'s>(i: &mut &'s str) -> Result<Token<'s>> {
dispatch! {peek(any);
'0'..='9' => digits.value(TokenKind::Value),
'(' => '('.value(TokenKind::OpenParen),
')' => ')'.value(TokenKind::CloseParen),
'+' => '+'.value(TokenKind::Oper(Oper::Add)),
'-' => '-'.value(TokenKind::Oper(Oper::Sub)),
'*' => '*'.value(TokenKind::Oper(Oper::Mul)),
'/' => '/'.value(TokenKind::Oper(Oper::Div)),
' '| '\t'| '\r'| '\n' => fail,
_ => take_till(.., ('0'..='9', '(', ')', '+', '-', '*', '/')).value(TokenKind::Unknown),
}
.with_taken()
.map(|(kind, raw)| Token { kind, raw })
.parse_next(i)
}
#[derive(Debug, Clone)]
pub(crate) enum Expr {
Value(i64),
Add(Box<Expr>, Box<Expr>),
Sub(Box<Expr>, Box<Expr>),
Mul(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>),
Paren(Box<Expr>),
}
impl Expr {
pub(crate) fn eval(&self) -> i64 {
match self {
Self::Value(v) => *v,
Self::Add(lhs, rhs) => lhs.eval() + rhs.eval(),
Self::Sub(lhs, rhs) => lhs.eval() - rhs.eval(),
Self::Mul(lhs, rhs) => lhs.eval() * rhs.eval(),
Self::Div(lhs, rhs) => lhs.eval() / rhs.eval(),
Self::Paren(expr) => expr.eval(),
}
}
}
impl Display for Expr {
fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result {
use Expr::{Add, Div, Mul, Paren, Sub, Value};
match *self {
Value(val) => write!(format, "{val}"),
Add(ref left, ref right) => write!(format, "{left} + {right}"),
Sub(ref left, ref right) => write!(format, "{left} - {right}"),
Mul(ref left, ref right) => write!(format, "{left} * {right}"),
Div(ref left, ref right) => write!(format, "{left} / {right}"),
Paren(ref expr) => write!(format, "({expr})"),
}
}
}
pub(crate) type Tokens<'i> = TokenSlice<'i, Token<'i>>;
/// Parse the tokens lexed in [`tokens`]
pub(crate) fn expr(i: &mut Tokens<'_>) -> Result<Expr> {
let init = term.parse_next(i)?;
let expr = repeat(
0..,
(
one_of([TokenKind::Oper(Oper::Add), TokenKind::Oper(Oper::Sub)]),
term,
),
)
.fold(
move || init.clone(),
|acc, (op, val): (&Token<'_>, Expr)| {
if op.kind == TokenKind::Oper(Oper::Add) {
Expr::Add(Box::new(acc), Box::new(val))
} else {
Expr::Sub(Box::new(acc), Box::new(val))
}
},
)
.parse_next(i)?;
opt(TokenKind::Eof).parse_next(i)?;
Ok(expr)
}
pub(crate) fn term(i: &mut Tokens<'_>) -> Result<Expr> {
let init = factor.parse_next(i)?;
repeat(
0..,
(
one_of([TokenKind::Oper(Oper::Mul), TokenKind::Oper(Oper::Div)]),
factor,
),
)
.fold(
move || init.clone(),
|acc, (op, val): (&Token<'_>, Expr)| {
if op.kind == TokenKind::Oper(Oper::Mul) {
Expr::Mul(Box::new(acc), Box::new(val))
} else {
Expr::Div(Box::new(acc), Box::new(val))
}
},
)
.parse_next(i)
}
pub(crate) fn factor(i: &mut Tokens<'_>) -> Result<Expr> {
alt((
TokenKind::Value.try_map(|t: &Token<'_>| t.raw.parse::<i64>().map(Expr::Value)),
parens,
))
.parse_next(i)
}
fn parens(i: &mut Tokens<'_>) -> Result<Expr> {
delimited(TokenKind::OpenParen, expr, TokenKind::CloseParen)
.map(|e| Expr::Paren(Box::new(e)))
.parse_next(i)
}

View File

@@ -0,0 +1,186 @@
use snapbox::assert_data_eq;
use snapbox::prelude::*;
use snapbox::str;
use winnow::prelude::*;
use crate::parser::*;
#[test]
fn factor_test() {
let input = "3";
let expected = str![[r#"
Ok(
(
"",
3,
),
)
"#]];
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
let input = " 12";
let expected = str![[r#"
Ok(
(
"",
12,
),
)
"#]];
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
let input = "537 ";
let expected = str![[r#"
Ok(
(
"",
537,
),
)
"#]];
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
let input = " 24 ";
let expected = str![[r#"
Ok(
(
"",
24,
),
)
"#]];
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
}
#[test]
fn term_test() {
let input = " 12 *2 / 3";
let expected = str![[r#"
Ok(
(
"",
8,
),
)
"#]];
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
let input = " 12 *2 / 3";
let expected = str![[r#"
Ok(
(
"",
8,
),
)
"#]];
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
let input = " 2* 3 *2 *2 / 3";
let expected = str![[r#"
Ok(
(
"",
8,
),
)
"#]];
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
let input = " 48 / 3/2";
let expected = str![[r#"
Ok(
(
"",
8,
),
)
"#]];
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
}
#[test]
fn expr_test() {
let input = " 1 + 2 ";
let expected = str![[r#"
Ok(
(
"",
3,
),
)
"#]];
assert_data_eq!(expr.parse_peek(input).to_debug(), expected);
let input = " 12 + 6 - 4+ 3";
let expected = str![[r#"
Ok(
(
"",
17,
),
)
"#]];
assert_data_eq!(expr.parse_peek(input).to_debug(), expected);
let input = " 1 + 2*3 + 4";
let expected = str![[r#"
Ok(
(
"",
11,
),
)
"#]];
assert_data_eq!(expr.parse_peek(input).to_debug(), expected);
}
#[test]
fn parens_test() {
let input = " ( 2 )";
let expected = str![[r#"
Ok(
(
"",
2,
),
)
"#]];
assert_data_eq!(expr.parse_peek(input).to_debug(), expected);
let input = " 2* ( 3 + 4 ) ";
let expected = str![[r#"
Ok(
(
"",
14,
),
)
"#]];
assert_data_eq!(expr.parse_peek(input).to_debug(), expected);
let input = " 2*2 / ( 5 - 1) + 3";
let expected = str![[r#"
Ok(
(
"",
4,
),
)
"#]];
assert_data_eq!(expr.parse_peek(input).to_debug(), expected);
}

View File

@@ -0,0 +1,317 @@
use snapbox::assert_data_eq;
use snapbox::prelude::*;
use snapbox::str;
use winnow::prelude::*;
use crate::parser_ast::*;
#[test]
fn factor_test() {
let input = "3";
let expected = str![[r#"
Ok(
(
"",
Value(
3,
),
),
)
"#]];
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
let input = " 12";
let expected = str![[r#"
Ok(
(
"",
Value(
12,
),
),
)
"#]];
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
let input = "537 ";
let expected = str![[r#"
Ok(
(
"",
Value(
537,
),
),
)
"#]];
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
let input = " 24 ";
let expected = str![[r#"
Ok(
(
"",
Value(
24,
),
),
)
"#]];
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
}
#[test]
fn term_test() {
let input = " 12 *2 / 3";
let expected = str![[r#"
Ok(
(
"",
Div(
Mul(
Value(
12,
),
Value(
2,
),
),
Value(
3,
),
),
),
)
"#]];
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
let input = " 12 *2 / 3";
let expected = str![[r#"
Ok(
(
"",
Div(
Mul(
Value(
12,
),
Value(
2,
),
),
Value(
3,
),
),
),
)
"#]];
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
let input = " 2* 3 *2 *2 / 3";
let expected = str![[r#"
Ok(
(
"",
Div(
Mul(
Mul(
Mul(
Value(
2,
),
Value(
3,
),
),
Value(
2,
),
),
Value(
2,
),
),
Value(
3,
),
),
),
)
"#]];
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
let input = " 48 / 3/2";
let expected = str![[r#"
Ok(
(
"",
Div(
Div(
Value(
48,
),
Value(
3,
),
),
Value(
2,
),
),
),
)
"#]];
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
}
#[test]
fn expr_test() {
let input = " 1 + 2 ";
let expected = str![[r#"
Ok(
Add(
Value(
1,
),
Value(
2,
),
),
)
"#]];
assert_data_eq!(expr.parse(input).to_debug(), expected);
let input = " 12 + 6 - 4+ 3";
let expected = str![[r#"
Ok(
Add(
Sub(
Add(
Value(
12,
),
Value(
6,
),
),
Value(
4,
),
),
Value(
3,
),
),
)
"#]];
assert_data_eq!(expr.parse(input).to_debug(), expected);
let input = " 1 + 2*3 + 4";
let expected = str![[r#"
Ok(
Add(
Add(
Value(
1,
),
Mul(
Value(
2,
),
Value(
3,
),
),
),
Value(
4,
),
),
)
"#]];
assert_data_eq!(expr.parse(input).to_debug(), expected);
}
#[test]
fn parens_test() {
let input = " ( 2 )";
let expected = str![[r#"
Ok(
Paren(
Value(
2,
),
),
)
"#]];
assert_data_eq!(expr.parse(input).to_debug(), expected);
let input = " 2* ( 3 + 4 ) ";
let expected = str![[r#"
Ok(
Mul(
Value(
2,
),
Paren(
Add(
Value(
3,
),
Value(
4,
),
),
),
),
)
"#]];
assert_data_eq!(expr.parse(input).to_debug(), expected);
let input = " 2*2 / ( 5 - 1) + 3";
let expected = str![[r#"
Ok(
Add(
Div(
Mul(
Value(
2,
),
Value(
2,
),
),
Paren(
Sub(
Value(
5,
),
Value(
1,
),
),
),
),
Value(
3,
),
),
)
"#]];
assert_data_eq!(expr.parse(input).to_debug(), expected);
}

View File

@@ -0,0 +1,438 @@
use snapbox::assert_data_eq;
use snapbox::prelude::*;
use snapbox::str;
use winnow::prelude::*;
use crate::parser_lexer::*;
#[test]
fn lex_test() {
let input = "3";
let expected = str![[r#"
Ok(
(
"",
[
"3",
Eof,
],
),
)
"#]];
assert_data_eq!(tokens.parse_peek(input).to_debug(), expected);
let input = " 24 ";
let expected = str![[r#"
Ok(
(
"",
[
"24",
Eof,
],
),
)
"#]];
assert_data_eq!(tokens.parse_peek(input).to_debug(), expected);
let input = " 12 *2 / 3";
let expected = str![[r#"
Ok(
(
"",
[
"12",
Mul,
"2",
Div,
"3",
Eof,
],
),
)
"#]];
assert_data_eq!(tokens.parse_peek(input).to_debug(), expected);
let input = " 2*2 / ( 5 - 1) + 3";
let expected = str![[r#"
Ok(
(
"",
[
"2",
Mul,
"2",
Div,
OpenParen,
"5",
Sub,
"1",
CloseParen,
Add,
"3",
Eof,
],
),
)
"#]];
assert_data_eq!(tokens.parse_peek(input).to_debug(), expected);
}
#[test]
fn factor_test() {
let input = "3";
let expected = str![[r#"
Ok(
(
[
Eof,
],
Value(
3,
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
let input = " 12";
let expected = str![[r#"
Ok(
(
[
Eof,
],
Value(
12,
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
let input = "537 ";
let expected = str![[r#"
Ok(
(
[
Eof,
],
Value(
537,
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
let input = " 24 ";
let expected = str![[r#"
Ok(
(
[
Eof,
],
Value(
24,
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(factor.parse_peek(input).to_debug(), expected);
}
#[test]
fn term_test() {
let input = " 12 *2 / 3";
let expected = str![[r#"
Ok(
(
[
Eof,
],
Div(
Mul(
Value(
12,
),
Value(
2,
),
),
Value(
3,
),
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
let input = " 12 *2 / 3";
let expected = str![[r#"
Ok(
(
[
Eof,
],
Div(
Mul(
Value(
12,
),
Value(
2,
),
),
Value(
3,
),
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
let input = " 2* 3 *2 *2 / 3";
let expected = str![[r#"
Ok(
(
[
Eof,
],
Div(
Mul(
Mul(
Mul(
Value(
2,
),
Value(
3,
),
),
Value(
2,
),
),
Value(
2,
),
),
Value(
3,
),
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
let input = " 48 / 3/2";
let expected = str![[r#"
Ok(
(
[
Eof,
],
Div(
Div(
Value(
48,
),
Value(
3,
),
),
Value(
2,
),
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(term.parse_peek(input).to_debug(), expected);
}
#[test]
fn expr_test() {
let input = " 1 + 2 ";
let expected = str![[r#"
Ok(
Add(
Value(
1,
),
Value(
2,
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(expr.parse(input).to_debug(), expected);
let input = " 12 + 6 - 4+ 3";
let expected = str![[r#"
Ok(
Add(
Sub(
Add(
Value(
12,
),
Value(
6,
),
),
Value(
4,
),
),
Value(
3,
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(expr.parse(input).to_debug(), expected);
let input = " 1 + 2*3 + 4";
let expected = str![[r#"
Ok(
Add(
Add(
Value(
1,
),
Mul(
Value(
2,
),
Value(
3,
),
),
),
Value(
4,
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(expr.parse(input).to_debug(), expected);
}
#[test]
fn parens_test() {
let input = " ( 2 )";
let expected = str![[r#"
Ok(
Paren(
Value(
2,
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(expr.parse(input).to_debug(), expected);
let input = " 2* ( 3 + 4 ) ";
let expected = str![[r#"
Ok(
Mul(
Value(
2,
),
Paren(
Add(
Value(
3,
),
Value(
4,
),
),
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(expr.parse(input).to_debug(), expected);
let input = " 2*2 / ( 5 - 1) + 3";
let expected = str![[r#"
Ok(
Add(
Div(
Mul(
Value(
2,
),
Value(
2,
),
),
Paren(
Sub(
Value(
5,
),
Value(
1,
),
),
),
),
Value(
3,
),
),
)
"#]];
let input = tokens.parse(input).unwrap();
let input = Tokens::new(&input);
assert_data_eq!(expr.parse(input).to_debug(), expected);
}