diff options
Diffstat (limited to 'vendor/pest/examples')
-rw-r--r-- | vendor/pest/examples/parens.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/vendor/pest/examples/parens.rs b/vendor/pest/examples/parens.rs new file mode 100644 index 000000000..2720f6346 --- /dev/null +++ b/vendor/pest/examples/parens.rs @@ -0,0 +1,75 @@ +extern crate pest; + +use std::io::{self, Write}; + +use pest::error::Error; +use pest::iterators::Pairs; +use pest::{state, ParseResult, Parser, ParserState}; + +#[allow(dead_code, non_camel_case_types)] +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +enum Rule { + expr, + paren, + paren_end, +} + +struct ParenParser; + +impl Parser<Rule> for ParenParser { + fn parse(rule: Rule, input: &str) -> Result<Pairs<Rule>, Error<Rule>> { + fn expr(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> { + state.sequence(|s| s.repeat(|s| paren(s)).and_then(|s| s.end_of_input())) + } + + fn paren(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> { + state.rule(Rule::paren, |s| { + s.sequence(|s| { + s.match_string("(") + .and_then(|s| { + s.optional(|s| { + s.sequence(|s| { + s.lookahead(true, |s| s.match_string("(")) + .and_then(|s| s.repeat(|s| paren(s))) + }) + }) + }) + .and_then(|s| s.rule(Rule::paren_end, |s| s.match_string(")"))) + }) + }) + } + + state(input, |state| match rule { + Rule::expr => expr(state), + Rule::paren => paren(state), + _ => unreachable!(), + }) + } +} + +#[derive(Debug)] +struct Paren(Vec<Paren>); + +fn expr(pairs: Pairs<Rule>) -> Vec<Paren> { + pairs + .filter(|p| p.as_rule() == Rule::paren) + .map(|p| Paren(expr(p.into_inner()))) + .collect() +} + +fn main() { + loop { + let mut line = String::new(); + + print!("> "); + io::stdout().flush().unwrap(); + + io::stdin().read_line(&mut line).unwrap(); + line.pop(); + + match ParenParser::parse(Rule::expr, &line) { + Ok(pairs) => println!("{:?}", expr(pairs)), + Err(e) => println!("\n{}", e), + }; + } +} |