Skip to content

Commit

Permalink
Merge pull request #175 from epage/example
Browse files Browse the repository at this point in the history
docs(cookbook): Bring in more examples
  • Loading branch information
epage committed Feb 17, 2023
2 parents 1215702 + f58d947 commit ed6333b
Show file tree
Hide file tree
Showing 15 changed files with 401 additions and 340 deletions.
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

0 comments on commit ed6333b

Please sign in to comment.