summaryrefslogtreecommitdiffstats
path: root/vendor/pest_meta/src/ast.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/pest_meta/src/ast.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/pest_meta/src/ast.rs')
-rw-r--r--vendor/pest_meta/src/ast.rs315
1 files changed, 315 insertions, 0 deletions
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
+// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
+// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<i32>),
+ /// Positive lookahead; matches expression without making progress, e.g. `&e`
+ PosPred(Box<Expr>),
+ /// Negative lookahead; matches if expression doesn't match, without making progress, e.g. `!e`
+ NegPred(Box<Expr>),
+ /// Matches a sequence of two expressions, e.g. `e1 ~ e2`
+ Seq(Box<Expr>, Box<Expr>),
+ /// Matches either of two expressions, e.g. `e1 | e2`
+ Choice(Box<Expr>, Box<Expr>),
+ /// Optionally matches an expression, e.g. `e?`
+ Opt(Box<Expr>),
+ /// Matches an expression zero or more times, e.g. `e*`
+ Rep(Box<Expr>),
+ /// Matches an expression one or more times, e.g. `e+`
+ RepOnce(Box<Expr>),
+ /// Matches an expression an exact number of times, e.g. `e{n}`
+ RepExact(Box<Expr>, u32),
+ /// Matches an expression at least a number of times, e.g. `e{n,}`
+ RepMin(Box<Expr>, u32),
+ /// Matches an expression at most a number of times, e.g. `e{,n}`
+ RepMax(Box<Expr>, u32),
+ /// Matches an expression a number of times within a range, e.g. `e{m, n}`
+ RepMinMax(Box<Expr>, u32, u32),
+ /// Continues to match expressions until one of the strings in the `Vec` is found
+ Skip(Vec<String>),
+ /// Matches an expression and pushes it to the stack, e.g. `push(e)`
+ Push(Box<Expr>),
+}
+
+impl Expr {
+ pub fn iter_top_down(&self) -> ExprTopDownIterator {
+ ExprTopDownIterator::new(self)
+ }
+
+ pub fn map_top_down<F>(self, mut f: F) -> Expr
+ where
+ F: FnMut(Expr) -> Expr,
+ {
+ fn map_internal<F>(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<F>(self, mut f: F) -> Expr
+ where
+ F: FnMut(Expr) -> Expr,
+ {
+ fn map_internal<F>(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<Expr>,
+ next: Option<Expr>,
+ right_branches: Vec<Expr>,
+}
+
+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<Self::Item> {
+ 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
+ );
+ }
+}