Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/binary_tree/bin_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub struct BinTreeBuilder();
impl TreeBuilder for BinTreeBuilder {
type Node = BinTree;

fn new_inner(&mut self, left: Self::Node, right: Self::Node) -> Self::Node {
fn new_inner(&mut self, _id: NodeIdx, left: Self::Node, right: Self::Node) -> Self::Node {
BinTree::Node(Box::new((left, right)))
}

Expand Down
2 changes: 1 addition & 1 deletion src/binary_tree/depth_first_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ mod tests {
#[test]
fn dfs() {
let tree = BinTreeBuilder::default()
.parse_newick_from_str("((3,1),2);")
.parse_newick_from_str("((3,1),2);", NodeIdx::new(0))
.unwrap();
let mut trav = tree.dfs();

Expand Down
54 changes: 54 additions & 0 deletions src/binary_tree/indexed_bin_tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use super::*;

/// Minimalistic implementation of a binary tree without any meta information
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum IndexedBinTree {
Node(Box<(NodeIdx, IndexedBinTree, IndexedBinTree)>),
Leaf(Label),
}

impl IndexedBinTree {
pub fn top_down(&self) -> &Self {
self
}
}

impl TopDownCursor for &IndexedBinTree {
fn children(&self) -> Option<(Self, Self)> {
match self {
IndexedBinTree::Node(b) => Some((&b.as_ref().1, &b.as_ref().2)),
IndexedBinTree::Leaf(_) => None,
}
}

fn leaf_label(&self) -> Option<Label> {
match self {
IndexedBinTree::Leaf(l) => Some(*l),
IndexedBinTree::Node(_) => None,
}
}
}

impl TreeWithNodeIdx for IndexedBinTree {
fn node_idx(&self) -> NodeIdx {
match self {
IndexedBinTree::Node(b) => b.0,
IndexedBinTree::Leaf(label) => (*label).into(),
}
}
}

#[derive(Default)]
pub struct IndexedBinTreeBuilder();

impl TreeBuilder for IndexedBinTreeBuilder {
type Node = IndexedBinTree;

fn new_inner(&mut self, idx: NodeIdx, left: Self::Node, right: Self::Node) -> Self::Node {
IndexedBinTree::Node(Box::new((idx, left, right)))
}

fn new_leaf(&mut self, label: Label) -> Self::Node {
IndexedBinTree::Leaf(label)
}
}
46 changes: 37 additions & 9 deletions src/binary_tree/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
pub mod bin_tree;
pub use bin_tree::*;
pub mod indexed_bin_tree;
pub use indexed_bin_tree::*;

pub mod depth_first_search;
pub use depth_first_search::DepthFirstSearch;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NodeIdx(pub u32);

impl NodeIdx {
pub fn new(v: u32) -> Self {
NodeIdx(v)
}

pub fn incremented(self) -> Self {
NodeIdx(self.0 + 1)
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Label(pub u32);

impl From<Label> for NodeIdx {
fn from(value: Label) -> Self {
NodeIdx(value.0)
}
}

pub trait TreeBuilder {
type Node;

Expand All @@ -19,12 +40,12 @@ pub trait TreeBuilder {
/// let mut builder = BinTreeBuilder::default();
/// let l1 = builder.new_leaf(Label(1));
/// let l2 = builder.new_leaf(Label(2));
/// let root = builder.new_inner(l1,l2);
/// let root = builder.new_inner(NodeIdx::new(0), l1,l2);
///
/// assert!( root.top_down().is_inner());
/// assert!(!root.top_down().is_leaf());
/// ```
fn new_inner(&mut self, left: Self::Node, right: Self::Node) -> Self::Node;
fn new_inner(&mut self, id: NodeIdx, left: Self::Node, right: Self::Node) -> Self::Node;

/// Creates a new leaf node with the label provided.
///
Expand All @@ -50,7 +71,7 @@ pub trait TreeBuilder {
/// let mut builder = BinTreeBuilder::default();
/// let l1 = builder.new_leaf(Label(1));
/// let l2 = builder.new_leaf(Label(2));
/// let root = builder.new_inner(l1,l2);
/// let root = builder.new_inner(NodeIdx::new(0),l1,l2);
/// let root = builder.make_root(root);
///
/// assert!( root.top_down().is_inner());
Expand All @@ -73,7 +94,7 @@ pub trait TopDownCursor: Sized {
/// assert!(l1.top_down().children().is_none());
///
/// let l2 = builder.new_leaf(Label(2));
/// let root = builder.new_inner(l1, l2);
/// let root = builder.new_inner(NodeIdx::new(0), l1, l2);
///
/// assert!(root.top_down().children().is_some());
/// assert!(root.top_down().children().unwrap().0.is_leaf());
Expand All @@ -89,7 +110,7 @@ pub trait TopDownCursor: Sized {
/// let mut builder = BinTreeBuilder::default();
/// let left_leaf = builder.new_leaf(Label(3141));
/// let right_leaf = builder.new_leaf(Label(1234));
/// let root = builder.new_inner(left_leaf, right_leaf);
/// let root = builder.new_inner(NodeIdx::new(0), left_leaf, right_leaf);
///
/// assert_eq!(root.top_down().left_child().unwrap().leaf_label(), Some(Label(3141)));
/// ```
Expand All @@ -106,7 +127,7 @@ pub trait TopDownCursor: Sized {
/// let mut builder = BinTreeBuilder::default();
/// let left_leaf = builder.new_leaf(Label(3141));
/// let right_leaf = builder.new_leaf(Label(1234));
/// let root = builder.new_inner(left_leaf, right_leaf);
/// let root = builder.new_inner(NodeIdx::new(0), left_leaf, right_leaf);
///
/// assert_eq!(root.top_down().right_child().unwrap().leaf_label(), Some(Label(1234)));
/// ```
Expand All @@ -122,7 +143,7 @@ pub trait TopDownCursor: Sized {
///
/// let mut builder = BinTreeBuilder::default();
/// let leaf = builder.new_leaf(Label(1337));
/// let root = builder.new_inner(leaf.clone(), leaf.clone());
/// let root = builder.new_inner(NodeIdx::new(0), leaf.clone(), leaf.clone());
///
/// assert_eq!(leaf.top_down().leaf_label().unwrap(), Label(1337));
/// assert!( root.top_down().leaf_label().is_none());
Expand All @@ -137,7 +158,7 @@ pub trait TopDownCursor: Sized {
///
/// let mut builder = BinTreeBuilder::default();
/// let leaf = builder.new_leaf(Label(1));
/// let root = builder.new_inner(leaf.clone(), leaf.clone());
/// let root = builder.new_inner(NodeIdx::new(0), leaf.clone(), leaf.clone());
///
/// assert!( root.top_down().is_inner());
/// assert!(!leaf.top_down().is_inner());
Expand All @@ -154,7 +175,7 @@ pub trait TopDownCursor: Sized {
///
/// let mut builder = BinTreeBuilder::default();
/// let leaf = builder.new_leaf(Label(1));
/// let root = builder.new_inner(leaf.clone(), leaf.clone());
/// let root = builder.new_inner(NodeIdx::new(0), leaf.clone(), leaf.clone());
///
/// assert!(!root.top_down().is_leaf());
/// assert!( leaf.top_down().is_leaf());
Expand All @@ -163,3 +184,10 @@ pub trait TopDownCursor: Sized {
self.leaf_label().is_some()
}
}

/// Tree with indexed inner nodes
pub trait TreeWithNodeIdx {
/// Returns the index of the node. If the node is a leaf,
/// the leaf label is converted into a node index.
fn node_idx(&self) -> NodeIdx;
}
83 changes: 68 additions & 15 deletions src/newick/binary_tree_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,19 @@ pub enum ParserError {
}

pub trait BinaryTreeParser: TreeBuilder + Sized {
fn parse_newick_from_lexer(&mut self, lexer: &mut Lexer) -> Result<Self::Node, ParserError>;

fn parse_newick_from_str(&mut self, text: &str) -> Result<Self::Node, ParserError> {
fn parse_newick_from_lexer(
&mut self,
lexer: &mut Lexer,
root_id: NodeIdx,
) -> Result<Self::Node, ParserError>;

fn parse_newick_from_str(
&mut self,
text: &str,
root_id: NodeIdx,
) -> Result<Self::Node, ParserError> {
let mut lexer = Lexer::new(text);
self.parse_newick_from_lexer(&mut lexer)
self.parse_newick_from_lexer(&mut lexer, root_id)
}
}

Expand All @@ -45,34 +53,42 @@ fn assert_next_token_else(
}
}

fn parse_inner<B: TreeBuilder>(builder: &mut B, lexer: &mut Lexer) -> Result<B::Node, ParserError> {
fn parse_inner<B: TreeBuilder>(
builder: &mut B,
lexer: &mut Lexer,
own_id: NodeIdx,
) -> Result<(B::Node, NodeIdx), ParserError> {
let token = lexer.next().ok_or(ParserError::UnexpectedEnd)??;

match token.token_type {
TokenType::ParOpen => {
let left_child = parse_inner(builder, lexer)?;
let (left_child, next_id) = parse_inner(builder, lexer, own_id.incremented())?;

assert_next_token_else(lexer, TokenType::Comma, |token| {
ParserError::ExpectedComma { token }
})?;

let right_child = parse_inner(builder, lexer)?;
let (right_child, next_id) = parse_inner(builder, lexer, next_id)?;

assert_next_token_else(lexer, TokenType::ParClose, |token| {
ParserError::ExpectedClosing { token }
})?;

Ok(builder.new_inner(left_child, right_child))
Ok((builder.new_inner(own_id, left_child, right_child), next_id))
}

TokenType::Number(x) => Ok(builder.new_leaf(Label(x))),
TokenType::Number(x) => Ok((builder.new_leaf(Label(x)), own_id)),
_ => Err(ParserError::ExpectedNodeBegin { token }),
}
}

impl<B: TreeBuilder> BinaryTreeParser for B {
fn parse_newick_from_lexer(&mut self, lexer: &mut Lexer) -> Result<Self::Node, ParserError> {
let tree = parse_inner(self, lexer)?;
fn parse_newick_from_lexer(
&mut self,
lexer: &mut Lexer,
root_id: NodeIdx,
) -> Result<Self::Node, ParserError> {
let (tree, _) = parse_inner(self, lexer, root_id)?;

assert_next_token_else(lexer, TokenType::Semicolon, |token| {
ParserError::ExpectedEnd { token }
Expand All @@ -87,10 +103,28 @@ mod test {
use super::*;
use crate::newick::*;

fn navigate<T: TopDownCursor>(mut cursor: T, path: &str) -> Option<T> {
for x in path.chars() {
match x {
'l' => {
cursor = cursor.left_child()?;
}

'r' => {
cursor = cursor.right_child()?;
}

_ => panic!("Unknown char"),
}
}

Some(cursor)
}

#[test]
fn leaf() {
let tree = BinTreeBuilder::default()
.parse_newick_from_str("132;")
.parse_newick_from_str("132;", NodeIdx::new(0))
.unwrap();
assert_eq!(tree.top_down().leaf_label(), Some(Label(132)));
}
Expand All @@ -100,7 +134,7 @@ mod test {
#[test]
fn $ident() {
let result = BinTreeBuilder::default()
.parse_newick_from_str($text)
.parse_newick_from_str($text, NodeIdx(0))
.unwrap_err();
assert!(matches!(result, $expect), "Got: {result:?}");
}
Expand All @@ -126,7 +160,7 @@ mod test {
let mut lexer = Lexer::new(" ( ( 0 , 1 ) , 2 ) ;");
lexer.allow_whitespaces();
let tree = BinTreeBuilder::default()
.parse_newick_from_lexer(&mut lexer)
.parse_newick_from_lexer(&mut lexer, NodeIdx::new(0))
.expect("A valid binary tree");
let lc = tree.top_down().left_child().unwrap();

Expand All @@ -142,7 +176,7 @@ mod test {
fn parser_writer_roundtrip() {
fn test_string(text: &str) {
let tree = BinTreeBuilder::default()
.parse_newick_from_str(text)
.parse_newick_from_str(text, NodeIdx::new(0))
.unwrap();
assert_eq!(text, tree.top_down().to_newick_string());
}
Expand All @@ -152,4 +186,23 @@ mod test {
test_string("(1,(5,91234));");
test_string("(((4,2),(7,1)),8);");
}

#[test]
fn parser_indexed_bintree() {
let tree = IndexedBinTreeBuilder::default()
.parse_newick_from_str("((1,2),(3,(5,4)));", NodeIdx::new(6))
.unwrap();

assert_eq!(tree.node_idx(), NodeIdx::new(6));

let td = tree.top_down();
assert_eq!(navigate(td, "l").unwrap().node_idx(), NodeIdx::new(7));
assert_eq!(navigate(td, "ll").unwrap().node_idx(), NodeIdx::new(1));
assert_eq!(navigate(td, "lr").unwrap().node_idx(), NodeIdx::new(2));
assert_eq!(navigate(td, "r").unwrap().node_idx(), NodeIdx::new(8));
assert_eq!(navigate(td, "rl").unwrap().node_idx(), NodeIdx::new(3));
assert_eq!(navigate(td, "rr").unwrap().node_idx(), NodeIdx::new(9));
assert_eq!(navigate(td, "rrl").unwrap().node_idx(), NodeIdx::new(5));
assert_eq!(navigate(td, "rrr").unwrap().node_idx(), NodeIdx::new(4));
}
}
2 changes: 1 addition & 1 deletion src/newick/binary_tree_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ mod test {

let l1 = build.new_leaf(Label(1234));
let l2 = build.new_leaf(Label(5678));
let tree = build.new_inner(l1, l2);
let tree = build.new_inner(NodeIdx::new(0), l1, l2);

assert_eq!(to_string(tree), "(1234,5678);");
}
Expand Down
4 changes: 2 additions & 2 deletions src/newick/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub trait NewickWriter {
/// let mut builder = BinTreeBuilder::default();
/// let l1 = builder.new_leaf(Label(1));
/// let l2 = builder.new_leaf(Label(2));
/// let tree = builder.new_inner(l1, l2);
/// let tree = builder.new_inner(NodeIdx::new(3), l1, l2);
///
/// let mut buffer : Vec<u8> = Vec::new();
/// tree.top_down().write_newick(&mut buffer).unwrap();
Expand All @@ -30,7 +30,7 @@ pub trait NewickWriter {
/// let mut builder = BinTreeBuilder::default();
/// let l1 = builder.new_leaf(Label(2));
/// let l2 = builder.new_leaf(Label(3));
/// let tree = builder.new_inner(l1, l2);
/// let tree = builder.new_inner(NodeIdx::new(0), l1, l2);
///
/// assert_eq!(tree.top_down().to_newick_string(), "(2,3);");
/// ```
Expand Down