From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/pest_meta/src/ast.rs | 315 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 vendor/pest_meta/src/ast.rs (limited to 'vendor/pest_meta/src/ast.rs') diff --git a/vendor/pest_meta/src/ast.rs b/vendor/pest_meta/src/ast.rs new file mode 100644 index 000000000..b80c59630 --- /dev/null +++ b/vendor/pest_meta/src/ast.rs @@ -0,0 +1,315 @@ +// pest. The Elegant Parser +// Copyright (c) 2018 DragoČ™ Tiselice +// +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , at your +// option. All files in the project carrying such notice may not be copied, +// modified, or distributed except according to those terms. + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Rule { + pub name: String, + pub ty: RuleType, + pub expr: Expr, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum RuleType { + Normal, + Silent, + Atomic, + CompoundAtomic, + NonAtomic, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Expr { + /// Matches an exact string, e.g. `"a"` + Str(String), + /// Matches an exact string, case insensitively (ASCII only), e.g. `^"a"` + Insens(String), + /// Matches one character in the range, e.g. `'a'..'z'` + Range(String, String), + /// Matches the rule with the given name, e.g. `a` + Ident(String), + /// Matches a custom part of the stack, e.g. `PEEK[..]` + PeekSlice(i32, Option), + /// Positive lookahead; matches expression without making progress, e.g. `&e` + PosPred(Box), + /// Negative lookahead; matches if expression doesn't match, without making progress, e.g. `!e` + NegPred(Box), + /// Matches a sequence of two expressions, e.g. `e1 ~ e2` + Seq(Box, Box), + /// Matches either of two expressions, e.g. `e1 | e2` + Choice(Box, Box), + /// Optionally matches an expression, e.g. `e?` + Opt(Box), + /// Matches an expression zero or more times, e.g. `e*` + Rep(Box), + /// Matches an expression one or more times, e.g. `e+` + RepOnce(Box), + /// Matches an expression an exact number of times, e.g. `e{n}` + RepExact(Box, u32), + /// Matches an expression at least a number of times, e.g. `e{n,}` + RepMin(Box, u32), + /// Matches an expression at most a number of times, e.g. `e{,n}` + RepMax(Box, u32), + /// Matches an expression a number of times within a range, e.g. `e{m, n}` + RepMinMax(Box, u32, u32), + /// Continues to match expressions until one of the strings in the `Vec` is found + Skip(Vec), + /// Matches an expression and pushes it to the stack, e.g. `push(e)` + Push(Box), +} + +impl Expr { + pub fn iter_top_down(&self) -> ExprTopDownIterator { + ExprTopDownIterator::new(self) + } + + pub fn map_top_down(self, mut f: F) -> Expr + where + F: FnMut(Expr) -> Expr, + { + fn map_internal(expr: Expr, f: &mut F) -> Expr + where + F: FnMut(Expr) -> Expr, + { + let expr = f(expr); + + match expr { + // TODO: Use box syntax when it gets stabilized. + Expr::PosPred(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::PosPred(mapped) + } + Expr::NegPred(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::NegPred(mapped) + } + Expr::Seq(lhs, rhs) => { + let mapped_lhs = Box::new(map_internal(*lhs, f)); + let mapped_rhs = Box::new(map_internal(*rhs, f)); + Expr::Seq(mapped_lhs, mapped_rhs) + } + Expr::Choice(lhs, rhs) => { + let mapped_lhs = Box::new(map_internal(*lhs, f)); + let mapped_rhs = Box::new(map_internal(*rhs, f)); + Expr::Choice(mapped_lhs, mapped_rhs) + } + Expr::Rep(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::Rep(mapped) + } + Expr::RepOnce(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::RepOnce(mapped) + } + Expr::RepExact(expr, max) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::RepExact(mapped, max) + } + Expr::RepMin(expr, num) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::RepMin(mapped, num) + } + Expr::RepMax(expr, num) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::RepMax(mapped, num) + } + Expr::RepMinMax(expr, min, max) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::RepMinMax(mapped, min, max) + } + Expr::Opt(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::Opt(mapped) + } + Expr::Push(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::Push(mapped) + } + expr => expr, + } + } + + map_internal(self, &mut f) + } + + pub fn map_bottom_up(self, mut f: F) -> Expr + where + F: FnMut(Expr) -> Expr, + { + fn map_internal(expr: Expr, f: &mut F) -> Expr + where + F: FnMut(Expr) -> Expr, + { + let mapped = match expr { + Expr::PosPred(expr) => { + // TODO: Use box syntax when it gets stabilized. + let mapped = Box::new(map_internal(*expr, f)); + Expr::PosPred(mapped) + } + Expr::NegPred(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::NegPred(mapped) + } + Expr::Seq(lhs, rhs) => { + let mapped_lhs = Box::new(map_internal(*lhs, f)); + let mapped_rhs = Box::new(map_internal(*rhs, f)); + Expr::Seq(mapped_lhs, mapped_rhs) + } + Expr::Choice(lhs, rhs) => { + let mapped_lhs = Box::new(map_internal(*lhs, f)); + let mapped_rhs = Box::new(map_internal(*rhs, f)); + Expr::Choice(mapped_lhs, mapped_rhs) + } + Expr::Rep(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::Rep(mapped) + } + Expr::RepOnce(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::RepOnce(mapped) + } + Expr::RepExact(expr, num) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::RepExact(mapped, num) + } + Expr::RepMin(expr, max) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::RepMin(mapped, max) + } + Expr::RepMax(expr, max) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::RepMax(mapped, max) + } + Expr::RepMinMax(expr, min, max) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::RepMinMax(mapped, min, max) + } + Expr::Opt(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::Opt(mapped) + } + Expr::Push(expr) => { + let mapped = Box::new(map_internal(*expr, f)); + Expr::Push(mapped) + } + expr => expr, + }; + + f(mapped) + } + + map_internal(self, &mut f) + } +} + +pub struct ExprTopDownIterator { + current: Option, + next: Option, + right_branches: Vec, +} + +impl ExprTopDownIterator { + pub fn new(expr: &Expr) -> Self { + let mut iter = ExprTopDownIterator { + current: None, + next: None, + right_branches: vec![], + }; + iter.iterate_expr(expr.clone()); + iter + } + + fn iterate_expr(&mut self, expr: Expr) { + self.current = Some(expr.clone()); + match expr { + Expr::Seq(lhs, rhs) => { + self.right_branches.push(*rhs); + self.next = Some(*lhs); + } + Expr::Choice(lhs, rhs) => { + self.right_branches.push(*rhs); + self.next = Some(*lhs); + } + Expr::PosPred(expr) + | Expr::NegPred(expr) + | Expr::Rep(expr) + | Expr::RepOnce(expr) + | Expr::RepExact(expr, _) + | Expr::RepMin(expr, _) + | Expr::RepMax(expr, _) + | Expr::RepMinMax(expr, ..) + | Expr::Opt(expr) + | Expr::Push(expr) => { + self.next = Some(*expr); + } + _ => { + self.next = None; + } + } + } +} + +impl Iterator for ExprTopDownIterator { + type Item = Expr; + + fn next(&mut self) -> Option { + let result = self.current.take(); + + if let Some(expr) = self.next.take() { + self.iterate_expr(expr); + } else if let Some(expr) = self.right_branches.pop() { + self.iterate_expr(expr); + } + + result + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn top_down_iterator() { + let expr = Expr::Choice( + Box::new(Expr::Str(String::from("a"))), + Box::new(Expr::Str(String::from("b"))), + ); + let mut top_down = expr.clone().iter_top_down(); + assert_eq!(top_down.next(), Some(expr)); + assert_eq!(top_down.next(), Some(Expr::Str(String::from("a")))); + assert_eq!(top_down.next(), Some(Expr::Str(String::from("b")))); + assert_eq!(top_down.next(), None); + } + + #[test] + fn identity() { + let expr = Expr::Choice( + Box::new(Expr::Seq( + Box::new(Expr::Ident("a".to_owned())), + Box::new(Expr::Str("b".to_owned())), + )), + Box::new(Expr::PosPred(Box::new(Expr::NegPred(Box::new(Expr::Rep( + Box::new(Expr::RepOnce(Box::new(Expr::Opt(Box::new(Expr::Choice( + Box::new(Expr::Insens("c".to_owned())), + Box::new(Expr::Push(Box::new(Expr::Range( + "'d'".to_owned(), + "'e'".to_owned(), + )))), + )))))), + )))))), + ); + + assert_eq!( + expr.clone() + .map_bottom_up(|expr| expr) + .map_top_down(|expr| expr), + expr + ); + } +} -- cgit v1.2.3