Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(cookbook): Bring in more examples #175

Merged
merged 14 commits into from
Feb 17, 2023
Merged
4 changes: 0 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ codegen-units = 1
[[example]]
name = "arithmetic"
test = true

[[example]]
name = "arithmetic_ast"
test = true
required-features = ["alloc"]

[[example]]
Expand Down
46 changes: 37 additions & 9 deletions examples/arithmetic/main.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
use winnow::prelude::*;

mod parser;

use parser::expr;
mod parser_ast;

fn main() -> Result<(), lexopt::Error> {
let args = Args::parse()?;

let input = args.input.as_deref().unwrap_or("1 + 1");

println!("{} =", input);
match expr.parse_next(input).finish() {
Ok(result) => {
println!(" {}", result);
}
Err(err) => {
println!(" {}", err);
}
match args.implementation {
Impl::Eval => match parser::expr.parse_next(input).finish() {
Ok(result) => {
println!(" {}", result);
}
Err(err) => {
println!(" {}", err);
}
},
Impl::Ast => match parser_ast::expr.parse_next(input).finish() {
Ok(result) => {
println!(" {:#?}", result);
}
Err(err) => {
println!(" {}", err);
}
},
}

Ok(())
Expand All @@ -25,6 +34,18 @@ fn main() -> Result<(), lexopt::Error> {
#[derive(Default)]
struct Args {
input: Option<String>,
implementation: Impl,
}

enum Impl {
Eval,
Ast,
}

impl Default for Impl {
fn default() -> Self {
Self::Eval
}
}

impl Args {
Expand All @@ -36,6 +57,13 @@ impl Args {
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),
_ => Err("expected `eval`, `ast`"),
})?;
}
Value(input) => {
res.input = Some(input.string()?);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use winnow::{
IResult,
};

#[derive(Debug)]
pub enum Expr {
Value(i64),
Add(Box<Expr>, Box<Expr>),
Expand All @@ -31,7 +32,7 @@ pub enum Oper {

impl Display for Expr {
fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result {
use self::Expr::{Add, Div, Mul, Paren, Sub, Value};
use Expr::{Add, Div, Mul, Paren, Sub, Value};
match *self {
Value(val) => write!(format, "{}", val),
Add(ref left, ref right) => write!(format, "{} + {}", left, right),
Expand All @@ -43,20 +44,6 @@ impl Display for Expr {
}
}

impl Debug for Expr {
fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result {
use self::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 fn expr(i: &str) -> IResult<&str, Expr> {
let (i, initial) = term(i)?;
let (i, remainder) = many0(alt((
Expand Down Expand Up @@ -122,38 +109,44 @@ fn fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr {
fn factor_test() {
assert_eq!(
factor(" 3 ").map(|(i, x)| (i, format!("{:?}", x))),
Ok(("", String::from("3")))
Ok(("", String::from("Value(3)")))
);
}

#[test]
fn term_test() {
assert_eq!(
term(" 3 * 5 ").map(|(i, x)| (i, format!("{:?}", x))),
Ok(("", String::from("(3 * 5)")))
Ok(("", String::from("Mul(Value(3), Value(5))")))
);
}

#[test]
fn expr_test() {
assert_eq!(
expr(" 1 + 2 * 3 ").map(|(i, x)| (i, format!("{:?}", x))),
Ok(("", String::from("(1 + (2 * 3))")))
Ok(("", String::from("Add(Value(1), Mul(Value(2), Value(3)))")))
);
assert_eq!(
expr(" 1 + 2 * 3 / 4 - 5 ").map(|(i, x)| (i, format!("{:?}", x))),
Ok(("", String::from("((1 + ((2 * 3) / 4)) - 5)")))
Ok((
"",
String::from("Sub(Add(Value(1), Div(Mul(Value(2), Value(3)), Value(4))), Value(5))")
))
);
assert_eq!(
expr(" 72 / 2 / 3 ").map(|(i, x)| (i, format!("{:?}", x))),
Ok(("", String::from("((72 / 2) / 3)")))
Ok(("", String::from("Div(Div(Value(72), Value(2)), Value(3))")))
);
}

#[test]
fn parens_test() {
assert_eq!(
expr(" ( 1 + 2 ) * 3 ").map(|(i, x)| (i, format!("{:?}", x))),
Ok(("", String::from("([(1 + 2)] * 3)")))
Ok((
"",
String::from("Mul(Paren(Add(Value(1), Value(2))), Value(3))")
))
);
}
47 changes: 0 additions & 47 deletions examples/arithmetic_ast/main.rs

This file was deleted.

20 changes: 20 additions & 0 deletions examples/s_expression/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! In this example we build an [S-expression](https://en.wikipedia.org/wiki/S-expression)
//! parser and tiny [lisp](https://en.wikipedia.org/wiki/Lisp_(programming_language)) interpreter.
//! Lisp is a simple type of language made up of Atoms and Lists, forming easily parsable trees.

#![cfg(feature = "alloc")]

mod parser;

fn main() {
let expression_1 = "((if (= (+ 3 (/ 9 3))
(* 2 3))
*
/)
456 123)";
println!(
"\"{}\"\nevaled gives us: {:?}",
expression_1,
parser::eval_from_str(expression_1)
);
}
Loading