Skip to content

Commit

Permalink
rangectlop visitor fixes and rangectlop parent implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
anweiss committed Oct 25, 2022
1 parent d0e2b76 commit 70a3e08
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ pub enum CDDLType<'a, 'b: 'a> {
Type1(&'b Type1<'a>),
Type2(&'b Type2<'a>),
Operator(&'b Operator<'a>),
RangeCtlOp(&'b RangeCtlOp),
ControlOperator(&'b ControlOperator),
Occurrence(&'b Occurrence<'a>),
Occur(Occur),
Value(Value<'a>),
Expand Down Expand Up @@ -87,6 +89,8 @@ cddl_types_from_ast! {
&'b Type1<'a> => CDDLType::Type1,
&'b Type2<'a> => CDDLType::Type2,
&'b Operator<'a> => CDDLType::Operator,
&'b RangeCtlOp => CDDLType::RangeCtlOp,
&'b ControlOperator => CDDLType::ControlOperator,
&'b Occurrence<'a> => CDDLType::Occurrence,
&'b ValueMemberKeyEntry<'a> => CDDLType::ValueMemberKeyEntry,
&'b TypeGroupnameEntry<'a> => CDDLType::TypeGroupnameEntry,
Expand Down
52 changes: 50 additions & 2 deletions src/validator/parent_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{
ast::*,
token::{ByteValue, Value},
token::{ByteValue, ControlOperator, Value},
visitor::{self, *},
};

Expand Down Expand Up @@ -64,6 +64,7 @@ impl_parent! {
TypeChoice<'a> => ([Type1<'a>], CDDLType::TypeChoice),
Type1<'a> => ([Operator<'a>, Type2<'a>], CDDLType::Type1),
Operator<'a> => ([Type2<'a>], CDDLType::Operator),
RangeCtlOp => ([ControlOperator], CDDLType::RangeCtlOp),
Type2<'a> => ([Identifier<'a>, GenericArgs<'a>, Type<'a>, Group<'a>], CDDLType::Type2),
Group<'a> => ([GroupChoice<'a>, Occurrence<'a>], CDDLType::Group),
GroupChoice<'a> => ([GroupEntry<'a>], CDDLType::GroupChoice),
Expand Down Expand Up @@ -325,7 +326,30 @@ impl<'a, 'b: 'a> Visitor<'a, 'b, Error> for ParentVisitor<'a, 'b> {
let child = self.arena_tree.node(CDDLType::Type2(&o.type2));
self.insert(parent, child)?;

walk_operator(self, target, o)
let child = self.arena_tree.node(CDDLType::RangeCtlOp(&o.operator));
self.insert(parent, child)?;

self.visit_rangectlop(&o.operator, target, &o.type2)
}

fn visit_rangectlop(
&mut self,
op: &'b RangeCtlOp,
target: &'b Type1<'a>,
controller: &'b Type2<'a>,
) -> visitor::Result<Error> {
match op {
RangeCtlOp::RangeOp { is_inclusive, .. } => {
self.visit_range(&target.type2, controller, *is_inclusive)
}
RangeCtlOp::CtlOp { ctrl, .. } => {
let parent = self.arena_tree.node(CDDLType::RangeCtlOp(op));
let child = self.arena_tree.node(CDDLType::ControlOperator(ctrl));
self.insert(parent, child)?;

self.visit_control_operator(&target.type2, *ctrl, controller)
}
}
}

fn visit_type2(&mut self, t2: &'b Type2<'a>) -> visitor::Result<Error> {
Expand Down Expand Up @@ -981,4 +1005,28 @@ mod tests {

Ok(())
}

#[test]
fn ctrl_parent_is_rangectlop() -> Result<()> {
let cddl = cddl_from_str(r#"ip4 = bstr .size 4"#, true).unwrap();
let pv = ParentVisitor::new(&cddl).unwrap();

if let Rule::Type { rule, .. } = cddl.rules.first().unwrap() {
if let op @ RangeCtlOp::CtlOp { ctrl, .. } = &rule
.value
.type_choices
.first()
.unwrap()
.type1
.operator
.as_ref()
.unwrap()
.operator
{
assert_eq!(ctrl.parent(&pv).unwrap(), op)
}
}

Ok(())
}
}
30 changes: 27 additions & 3 deletions src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ pub trait Visitor<'a, 'b, E: Error> {
walk_operator(self, target, o)
}

/// Visit rangectlop
fn visit_rangectlop(
&mut self,
op: &'b RangeCtlOp,
target: &'b Type1<'a>,
controller: &'b Type2<'a>,
) -> Result<E> {
walk_rangectlop(self, op, target, controller)
}

/// Visit range
fn visit_range(
&mut self,
Expand Down Expand Up @@ -244,12 +254,26 @@ where
E: Error,
V: Visitor<'a, 'b, E> + ?Sized,
{
match &o.operator {
visitor.visit_rangectlop(&o.operator, target, &o.type2)
}

/// Walk rangectlop
pub fn walk_rangectlop<'a, 'b, E, V>(
visitor: &mut V,
op: &'b RangeCtlOp,
target: &'b Type1<'a>,
controller: &'b Type2<'a>,
) -> Result<E>
where
E: Error,
V: Visitor<'a, 'b, E> + ?Sized,
{
match op {
RangeCtlOp::RangeOp { is_inclusive, .. } => {
visitor.visit_range(&target.type2, &o.type2, *is_inclusive)
visitor.visit_range(&target.type2, controller, *is_inclusive)
}
RangeCtlOp::CtlOp { ctrl, .. } => {
visitor.visit_control_operator(&target.type2, *ctrl, &o.type2)
visitor.visit_control_operator(&target.type2, *ctrl, controller)
}
}
}
Expand Down

0 comments on commit 70a3e08

Please sign in to comment.