summaryrefslogtreecommitdiff
path: root/src/chomp/check/closed.rs
diff options
context:
space:
mode:
authorGreg Brown <gmb60@cam.ac.uk>2021-01-08 18:00:11 +0000
committerGreg Brown <gmb60@cam.ac.uk>2021-01-08 18:00:11 +0000
commite1452227b8bd9ad3805480f8a5a66a75fb8370dd (patch)
treeb02c9dfdc157d753e3f1c8a09bbd2ffb0bbfcc36 /src/chomp/check/closed.rs
parentfe2eac31d9dbec772796c3ea75be32e9cd01b810 (diff)
Do more restructuring.
Diffstat (limited to 'src/chomp/check/closed.rs')
-rw-r--r--src/chomp/check/closed.rs50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/chomp/check/closed.rs b/src/chomp/check/closed.rs
new file mode 100644
index 0000000..07ef7ac
--- /dev/null
+++ b/src/chomp/check/closed.rs
@@ -0,0 +1,50 @@
+use super::super::{
+ ast::{Alt, Call, Cat, Epsilon, Fix, Literal, Parameter, Variable},
+ visit::{Visitable, Visitor},
+};
+
+/// Test if term is closed for a context with `depth` variables.
+#[derive(Copy, Clone, Debug, Default)]
+pub struct Closed {
+ depth: usize,
+ params: usize,
+}
+
+impl Visitor for Closed {
+ type Out = bool;
+
+ fn visit_epsilon(&mut self, _eps: &Epsilon) -> Self::Out {
+ true
+ }
+
+ fn visit_literal(&mut self, _lit: &Literal) -> Self::Out {
+ true
+ }
+
+ fn visit_cat(&mut self, cat: &Cat) -> Self::Out {
+ cat.first().visit(self) && cat.second().visit(self)
+ }
+
+ fn visit_alt(&mut self, alt: &Alt) -> Self::Out {
+ alt.left().visit(self) && alt.right().visit(self)
+ }
+
+ fn visit_fix(&mut self, fix: &Fix) -> Self::Out {
+ self.depth += 1;
+ let res = fix.inner().visit(self);
+ self.depth -= 1;
+ res
+ }
+
+ fn visit_variable(&mut self, var: &Variable) -> Self::Out {
+ var.index() < self.depth
+ }
+
+ fn visit_parameter(&mut self, param: &Parameter) -> Self::Out {
+ param.index() < self.params
+ }
+
+ fn visit_call(&mut self, call: &Call) -> Self::Out {
+ call.args().iter().all(|arg| arg.visit(self))
+ }
+}