diff options
Diffstat (limited to 'vendor/pest_derive/examples')
-rw-r--r-- | vendor/pest_derive/examples/calc.pest | 16 | ||||
-rw-r--r-- | vendor/pest_derive/examples/calc.rs | 109 |
2 files changed, 125 insertions, 0 deletions
diff --git a/vendor/pest_derive/examples/calc.pest b/vendor/pest_derive/examples/calc.pest new file mode 100644 index 000000000..9f2cc3b74 --- /dev/null +++ b/vendor/pest_derive/examples/calc.pest @@ -0,0 +1,16 @@ +WHITESPACE = _{ " " | "\t" | NEWLINE } + + program = { SOI ~ expr ~ EOI } + expr = { prefix* ~ primary ~ postfix* ~ (infix ~ prefix* ~ primary ~ postfix* )* } + infix = _{ add | sub | mul | div | pow } + add = { "+" } // Addition + sub = { "-" } // Subtraction + mul = { "*" } // Multiplication + div = { "/" } // Division + pow = { "^" } // Exponentiation + prefix = _{ neg } + neg = { "-" } // Negation + postfix = _{ fac } + fac = { "!" } // Factorial + primary = _{ int | "(" ~ expr ~ ")" } + int = @{ (ASCII_NONZERO_DIGIT ~ ASCII_DIGIT+ | ASCII_DIGIT) }
\ No newline at end of file diff --git a/vendor/pest_derive/examples/calc.rs b/vendor/pest_derive/examples/calc.rs new file mode 100644 index 000000000..efc6b7b22 --- /dev/null +++ b/vendor/pest_derive/examples/calc.rs @@ -0,0 +1,109 @@ +mod parser { + use pest_derive::Parser; + + #[derive(Parser)] + #[grammar = "../examples/calc.pest"] + pub struct Parser; +} + +use parser::Rule; +use pest::{ + iterators::Pairs, + pratt_parser::{Assoc::*, Op, PrattParser}, + Parser, +}; +use std::io::{stdin, stdout, Write}; + +fn parse_to_str(pairs: Pairs<Rule>, pratt: &PrattParser<Rule>) -> String { + pratt + .map_primary(|primary| match primary.as_rule() { + Rule::int => primary.as_str().to_owned(), + Rule::expr => parse_to_str(primary.into_inner(), pratt), + _ => unreachable!(), + }) + .map_prefix(|op, rhs| match op.as_rule() { + Rule::neg => format!("(-{})", rhs), + _ => unreachable!(), + }) + .map_postfix(|lhs, op| match op.as_rule() { + Rule::fac => format!("({}!)", lhs), + _ => unreachable!(), + }) + .map_infix(|lhs, op, rhs| match op.as_rule() { + Rule::add => format!("({}+{})", lhs, rhs), + Rule::sub => format!("({}-{})", lhs, rhs), + Rule::mul => format!("({}*{})", lhs, rhs), + Rule::div => format!("({}/{})", lhs, rhs), + Rule::pow => format!("({}^{})", lhs, rhs), + _ => unreachable!(), + }) + .parse(pairs) +} + +fn parse_to_i32(pairs: Pairs<Rule>, pratt: &PrattParser<Rule>) -> i128 { + pratt + .map_primary(|primary| match primary.as_rule() { + Rule::int => primary.as_str().parse().unwrap(), + Rule::expr => parse_to_i32(primary.into_inner(), pratt), + _ => unreachable!(), + }) + .map_prefix(|op, rhs| match op.as_rule() { + Rule::neg => -rhs, + _ => unreachable!(), + }) + .map_postfix(|lhs, op| match op.as_rule() { + Rule::fac => (1..lhs + 1).product(), + _ => unreachable!(), + }) + .map_infix(|lhs, op, rhs| match op.as_rule() { + Rule::add => lhs + rhs, + Rule::sub => lhs - rhs, + Rule::mul => lhs * rhs, + Rule::div => lhs / rhs, + Rule::pow => (1..rhs + 1).map(|_| lhs).product(), + _ => unreachable!(), + }) + .parse(pairs) +} + +fn main() { + let pratt = PrattParser::new() + .op(Op::infix(Rule::add, Left) | Op::infix(Rule::sub, Left)) + .op(Op::infix(Rule::mul, Left) | Op::infix(Rule::div, Left)) + .op(Op::infix(Rule::pow, Right)) + .op(Op::postfix(Rule::fac)) + .op(Op::prefix(Rule::neg)); + + let stdin = stdin(); + let mut stdout = stdout(); + + loop { + let source = { + print!("> "); + let _ = stdout.flush(); + let mut input = String::new(); + let _ = stdin.read_line(&mut input); + input.trim().to_string() + }; + + let pairs = match parser::Parser::parse(Rule::program, &source) { + Ok(mut parse_tree) => { + parse_tree + .next() + .unwrap() + .into_inner() // inner of program + .next() + .unwrap() + .into_inner() // inner of expr + } + Err(err) => { + println!("Failed parsing input: {:}", err); + continue; + } + }; + + print!("{} => ", source); + print!("{} => ", parse_to_str(pairs.clone(), &pratt)); + println!("{}", parse_to_i32(pairs.clone(), &pratt)); + } +} |