Rust 如何构造树结构,其中节点包含对包含树结构的字段的引用

Rust 如何构造树结构,其中节点包含对包含树结构的字段的引用,rust,Rust,我正在Rust中使用AST,我认为最好的一件事是,如果所有节点都可以简单地将片段包含到原始源字符串中,而不是复制周围的内存。然而,我不太清楚应该如何在代码中构建生命周期,以实现这个目标。我天真的尝试产生了这个程序: #[derive(Debug)] struct Node<'source> { slice : &'source str, nid : usize , parent : usize , chil

我正在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);
}
这不会编译,因为:

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

  • 因此,
    slice()
    self
    的可变引用需要比
    slice()
    函数调用更有效

  • 因此,在调用
    main
    函数中的
    tree.slice()
    之后,
    tree
    仍然是可变借用的

  • 因此,
    println宏无法编译

理想情况下,节点中的切片需要能够比
slice()
调用更长寿,但可变引用
self
不应该。我知道借阅检查器禁止这样做,因为
self
包含
source
字符串,切片引用到该字符串中


考虑到这一点,我如何重新构造代码以允许节点将切片包含到源代码中,而不必借用
self
的长度超过
slice
函数的长度?这是否可行,或者我需要求助于
不安全的

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

另一种方法是不拥有原始字符串,而是将AST与解析它的字符串的生存期绑定,例如

#[derive(Debug)]
struct Tree<'source> {
    source: &'source str,
    nodes : Vec<Node<'source>>,
}
#[派生(调试)]
如果所有节点都可以简单地将片段包含到原始源字符串中,那么struct tree将是一种非常有效的解析技术(我在几乎所有的解析器中都使用了这种技术),但您的代码并不是这样做的。