diff options
author | Greg Brown <gmb60@cam.ac.uk> | 2021-01-08 18:00:11 +0000 |
---|---|---|
committer | Greg Brown <gmb60@cam.ac.uk> | 2021-01-08 18:00:11 +0000 |
commit | e1452227b8bd9ad3805480f8a5a66a75fb8370dd (patch) | |
tree | b02c9dfdc157d753e3f1c8a09bbd2ffb0bbfcc36 /src/chomp/check/closed.rs | |
parent | fe2eac31d9dbec772796c3ea75be32e9cd01b810 (diff) |
Do more restructuring.
Diffstat (limited to 'src/chomp/check/closed.rs')
-rw-r--r-- | src/chomp/check/closed.rs | 50 |
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)) + } +} |