如何构造树结构,其中节点包含对包含树结构

时间:2018-03-20 20:01:25

标签: rust

我正在使用Rust中的AST,而且我认为一件事情是整齐的,如果所有节点都可以简单地将切片包含在原始源字符串中,而不是复制内存。但是,我无法解释如何构建代码中的生命周期,以实现此目标。我天真的尝试产生了这个程序:

#[derive(Debug)]
struct Node<'source> {
    slice   : &'source str,
    nid     : usize       ,
    parent  : usize       ,
    children: Vec<usize>  ,
}

#[derive(Debug)]
struct Tree<'source> {
    source: String            ,
    nodes : Vec<Node<'source>>,
}

impl<'source> Tree<'source> {
    fn new() -> Self {
        Tree {source: String::from("Hello World"), nodes: vec![]}
    }

    fn slice(&'source mut self, from: usize, to: usize) {
        let new_nid = self.nodes.len();
        self.nodes.push(
            Node { slice: &self.source[from..to], nid: new_nid, parent: 0, children: vec![] }
        );
    }
}


fn main() {
    let mut tree = Tree::new();
    tree.slice(2, 6);
    println!("{:?}", tree);
}

编译器输出:

error[E0502]: cannot borrow `tree` as immutable because it is also borrowed as mutable
  --> ast.rs:32:22
   |
31 |     tree.slice(2, 6);
   |     ---- mutable borrow occurs here
32 |     println!("{:?}", tree);
   |                      ^^^^ immutable borrow occurs here
33 | }
   | - mutable borrow ends here

这不能编译,因为:

  • 节点包含的切片需要比slice()函数调用更长久

  • 因此,selfslice()采取的可变引用需要比slice()函数调用更长。

  • 因此,在tree函数tree.slice()调用后,main仍然可以借用println!

  • 因此,slice()宏无法编译。

理想情况下,节点内的切片需要能够比self调用更长,但可变参考self不应该。我理解借用检查器是禁止的,因为source包含切片引用的self字符串。

考虑到这一点,我如何重构我的代码以允许节点将切片包含到源中,而不必借用slice超过unsafe函数的长度?这是否可行,或者我需要求助import Data.Char (digitToInt) expand :: String -> [(Char, Int)] expand (x:x':xs) = (x, digitToInt x'):expand xs expand _ = []

1 个答案:

答案 0 :(得分:1)

解决您问题的最简单方法是存储std::ops::Range<usize>而不是&str。然后,当您需要查看实际字符串时,在AST上提供一个方法,该方法需要Range<usize>并返回&str

另一种方法是不拥有原始字符串,而是将AST与其解析字符串的生命周期联系起来,例如,

#[derive(Debug)]
struct Tree<'source> {
    source: &'source str,
    nodes : Vec<Node<'source>>,
}

你无法按照设置的方式进行操作,因为Rust不知道如何检查兄弟借用。如果你四处寻找兄弟借款问题,那么你将获得更多的背景。

来源:reddit post