pub struct Builder<T, F = FlavorDefault>{ /* private fields */ }
Expand description
A builder for a Tree.
This maintains a stack of nodes being built which has to be balanced with
calls to Builder::open
and Builder::close
.
§Type parameters and bounds
The three type parameters of the tree determines the following properties:
T
is the data stored in the tree.I
determines the numerical bounds of spans stored in the tree through the Index trait, if set to Empty the tree does not store any spans.W
determines the bounds of pointers in the tree through the Width trait, this decides how many elements that can be stored in the tree.
To use the default values, use the Builder::new constructor.
§Examples
let mut tree = syntree::Builder::new();
tree.open("root")?;
tree.open("child")?;
tree.close()?;
tree.open("child")?;
tree.close()?;
tree.close()?;
let tree = tree.build()?;
let expected = syntree::tree! {
"root" => {
"child" => {},
"child" => {}
}
};
assert_eq!(tree, expected);
Implementations§
Source§impl<T> Builder<T, FlavorDefault>where
T: Copy,
impl<T> Builder<T, FlavorDefault>where
T: Copy,
Sourcepub const fn new() -> Self
pub const fn new() -> Self
Construct a new tree with a default Span
based on u32
.
For a constructor that can use custom bounds, use Builder::new_with.
§Examples
let mut tree = syntree::Builder::new();
tree.open("root")?;
tree.open("child")?;
tree.token("token", 5)?;
tree.close()?;
tree.open("child2")?;
tree.close()?;
tree.close()?;
let tree = tree.build()?;
let expected = syntree::tree! {
"root" => {
"child" => {
("token", 5)
},
"child2" => {}
}
};
assert_eq!(tree, expected);
Source§impl<T, F> Builder<T, F>
impl<T, F> Builder<T, F>
Sourcepub const fn new_with() -> Self
pub const fn new_with() -> Self
Construct a new tree with a custom span.
To build a tree with default bounds, see Builder::new. Also see the Builder documentation for what the different bounds means.
§Examples
use syntree::{Builder, Empty, EmptyVec, TreeIndex, Tree};
syntree::flavor! {
struct FlavorEmpty {
type Index = Empty;
type Width = u32;
type Indexes = EmptyVec<TreeIndex<Self>>;
}
}
let mut tree: Builder<_, FlavorEmpty> = Builder::new_with();
tree.open("root")?;
tree.open("child")?;
tree.token("token", Empty)?;
tree.close()?;
tree.open("child2")?;
tree.close()?;
tree.close()?;
let tree = tree.build()?;
let expected: Tree<_, FlavorEmpty> = syntree::tree_with! {
"root" => {
"child" => {
"token"
},
"child2" => {}
}
};
assert_eq!(tree, expected);
Sourcepub const fn cursor(&self) -> &F::Index
pub const fn cursor(&self) -> &F::Index
Get a reference to the current cursor position of the syntax tree.
The cursor position is the position in which it’s been advanced so far as a result of calls to Builder::token and indicates the current starting index of the next span.
§Examples
let mut tree = syntree::Builder::new();
assert_eq!(*tree.cursor(), 0);
tree.open("child")?;
assert_eq!(*tree.cursor(), 0);
tree.token("lit", 4)?;
assert_eq!(*tree.cursor(), 4);
tree.close()?;
assert_eq!(*tree.cursor(), 4);
let tree = tree.build()?;
let expected = syntree::tree! {
"child" => {
("lit", 4)
}
};
assert_eq!(tree, expected);
Sourcepub fn set_cursor(&mut self, cursor: F::Index)
pub fn set_cursor(&mut self, cursor: F::Index)
Set the cursor position of the syntax tree.
This is used to implicitly set spans when using spanless constructions methods.
§Examples
let mut tree = syntree::Builder::new();
assert_eq!(*tree.cursor(), 0);
tree.open("child")?;
assert_eq!(*tree.cursor(), 0);
tree.token("lit", 4)?;
assert_eq!(*tree.cursor(), 4);
tree.close()?;
assert_eq!(*tree.cursor(), 4);
let tree = tree.build()?;
let expected = syntree::tree! {
"child" => {
("lit", 4)
}
};
assert_eq!(tree, expected);
Sourcepub fn open(&mut self, data: T) -> Result<F::Pointer, Error<F::Error>>
pub fn open(&mut self, data: T) -> Result<F::Pointer, Error<F::Error>>
Start a node with the given data
.
This pushes a new link with the given type onto the stack which links
itself onto the last sibling node that ben introduced either through
Builder::close
, Builder::close_at
, or
Builder::close_at_with
.
§Errors
Errors with Error::Overflow
in case we run out of node
identifiers.
§Examples
let mut tree = syntree::Builder::new();
tree.open("root")?;
tree.open("child")?;
tree.close()?;
tree.open("child")?;
tree.close()?;
tree.close()?;
Sourcepub fn open_with(
&mut self,
data: T,
span: Span<F::Index>,
) -> Result<F::Pointer, Error<F::Error>>
pub fn open_with( &mut self, data: T, span: Span<F::Index>, ) -> Result<F::Pointer, Error<F::Error>>
Start a node with the given data
and span.
This pushes a new link with the given type onto the stack which links
itself onto the last sibling node that ben introduced either through
Builder::close
, Builder::close_at
or Builder::close_at_with
.
This does not advance the cursor position, in order to fix tree
construction use Builder::set_cursor
.
§Errors
Errors with Error::Overflow
in case we run out of node
identifiers.
§Examples
use syntree::Span;
let mut tree = syntree::Builder::new();
tree.open("root")?;
tree.open_with("child", Span::new(0, 3))?;
tree.close()?;
tree.open_with("child", Span::new(3, 6))?;
tree.close()?;
tree.close()?;
let tree = tree.build()?;
let expected = syntree::tree! {
("root", (0, 6)) => {
("child", (0, 3)) => {},
("child", (3, 6)) => {}
}
};
assert_eq!(tree, expected);
Sourcepub fn close(&mut self) -> Result<(), Error<F::Error>>
pub fn close(&mut self) -> Result<(), Error<F::Error>>
End a node being built.
This will pop a value of the stack, and set that value as the next
sibling which will be used with Builder::open
.
§Errors
This call must be balanced with a prior call to Builder::open
.
If not this will result in an Error::CloseError
being raised.
§Examples
let mut tree = syntree::Builder::new();
tree.open("root")?;
tree.open("child")?;
tree.close()?;
tree.open("child")?;
tree.close()?;
tree.close()?;
Sourcepub fn token(
&mut self,
value: T,
len: F::Length,
) -> Result<F::Pointer, Error<F::Error>>
pub fn token( &mut self, value: T, len: F::Length, ) -> Result<F::Pointer, Error<F::Error>>
Declare a token with the specified value
and a corresponding len
.
A token is always a terminating element without children.
§Errors
Errors with Error::Overflow
in case we run out of node
identifiers.
§Examples
let mut tree = syntree::Builder::new();
tree.open("child")?;
tree.token("lit", 4)?;
tree.close()?;
let tree = tree.build()?;
let expected = syntree::tree! {
"child" => {
("lit", 4)
}
};
assert_eq!(tree, expected);
Sourcepub fn token_with(
&mut self,
value: T,
span: Span<F::Index>,
) -> Result<F::Pointer, Error<F::Error>>
pub fn token_with( &mut self, value: T, span: Span<F::Index>, ) -> Result<F::Pointer, Error<F::Error>>
Insert a token with a custom span.
§Errors
Errors with Error::Overflow
in case we run out of node identifiers.
§Examples
use syntree::Span;
let mut tree = syntree::Builder::new();
tree.open_with("child", Span::new(0, 10))?;
tree.token_with("lit", Span::new(2, 4))?;
tree.token_with("lit2", Span::new(4, 6))?;
tree.close()?;
let tree = tree.build()?;
let expected = syntree::tree! {
("child", (0, 10)) => {
("lit", (2, 4)),
("lit2", (4, 6)),
}
};
assert_eq!(tree, expected);
Tokens with spans forces the cursor to be set to the end of the span.
use syntree::Span;
let mut tree = syntree::Builder::new();
tree.open("child")?;
tree.token_with("lit", Span::new(2, 4))?;
tree.token_with("lit2", Span::new(4, 6))?;
tree.token("lit3", 6)?;
tree.close()?;
let tree = tree.build()?;
let expected = syntree::tree! {
("child", (0, 6)) => {
("lit", (2, 4)),
("lit2", (4, 6)),
("lit3", (6, 12)),
}
};
assert_eq!(tree, expected);
Sourcepub fn token_empty(&mut self, value: T) -> Result<F::Pointer, Error<F::Error>>
pub fn token_empty(&mut self, value: T) -> Result<F::Pointer, Error<F::Error>>
Declare a token with the specified value
and an empty length.
A token is always a terminating element without children.
§Errors
Errors with Error::Overflow
in case we run out of node
identifiers.
§Examples
let mut tree = syntree::Builder::new();
tree.open("child")?;
tree.token_empty("lit")?;
tree.close()?;
let tree = tree.build()?;
let expected = syntree::tree! {
"child" => {
"lit"
}
};
assert_eq!(tree, expected);
Sourcepub fn checkpoint(&mut self) -> Result<Checkpoint<F::Pointer>, Error<F::Error>>
pub fn checkpoint(&mut self) -> Result<Checkpoint<F::Pointer>, Error<F::Error>>
Get a checkpoint corresponding to the current position in the tree.
§Mixing checkpoints
Note that using checkpoints from a different tree doesn’t have a
well-specified behavior - it might seemingly work or it might raise an
error during closing such as Error::MissingNode
.
The following is not well-defined, here we’re using a checkpoint for a different tree but it “just happens” to work because both trees have identical internal topologies:
use syntree::{Builder, Error};
let mut a = Builder::new();
let mut b = Builder::new();
let c = b.checkpoint()?;
a.open("child")?;
a.close()?;
b.open("child")?;
b.close()?;
// Checkpoint use from different tree.
a.close_at(&c, "root")?;
let unexpected = syntree::tree! {
"root" => {
"child"
}
};
assert_eq!(a.build()?, unexpected);
§Errors
Errors with Error::Overflow
in case we run out of node
identifiers.
§Panics
This panics if the number of nodes are too many to fit in a vector on
your architecture. This corresponds to usize::MAX
.
§Examples
let mut tree = syntree::Builder::new();
let c = tree.checkpoint()?;
tree.open("child")?;
tree.token("lit", 3)?;
tree.close()?;
tree.close_at(&c, "root")?;
let tree = tree.build()?;
let expected = syntree::tree! {
"root" => {
"child" => {
("lit", 3)
}
}
};
assert_eq!(tree, expected);
Sourcepub fn close_at(
&mut self,
c: &Checkpoint<F::Pointer>,
data: T,
) -> Result<F::Pointer, Error<F::Error>>
pub fn close_at( &mut self, c: &Checkpoint<F::Pointer>, data: T, ) -> Result<F::Pointer, Error<F::Error>>
Insert a node that wraps from the given checkpointed location.
§Errors
The checkpoint being closed must be a sibling. Otherwise a
Error::CloseAtError
will be raised.
This might also sporadically error with Error::MissingNode
, in case
a checkpoint is used that was constructed from another tree.
§Examples
let mut tree = syntree::Builder::new();
let c = tree.checkpoint()?;
tree.token("lit", 3)?;
tree.close_at(&c, "root")?;
let tree = tree.build()?;
let expected = syntree::tree! {
"root" => {
("lit", 3)
}
};
assert_eq!(tree, expected);
More complex example:
let mut tree = syntree::Builder::new();
let c = tree.checkpoint()?;
tree.open("number")?;
tree.token("lit", 3)?;
tree.close()?;
tree.token("whitespace", 1)?;
tree.open("number")?;
tree.token("lit", 2)?;
tree.close()?;
tree.close_at(&c, "root")?;
let tree = tree.build()?;
let expected = syntree::tree! {
"root" => {
"number" => {
("lit", 3)
},
("whitespace", 1),
"number" => {
("lit", 2)
},
}
};
assert_eq!(tree, expected);
Adding a token after a checkpoint:
let mut tree = syntree::Builder::new();
let c = tree.checkpoint()?;
tree.open("child")?;
tree.token("lit", 3)?;
tree.close()?;
tree.close_at(&c, "root")?;
tree.token("sibling", 3)?;
let tree = tree.build()?;
let child = tree.node_with_range(0..3).ok_or("missing at 0..3")?;
assert_eq!(child.value(), "child");
let lit = tree.first().and_then(|n| n.first()).and_then(|n| n.first()).ok_or("expected lit")?;
assert_eq!(lit.value(), "lit");
let root = lit.ancestors().last().ok_or("missing root")?;
assert_eq!(root.value(), "root");
assert_eq!(root.parent(), None);
let expected = syntree::tree! {
"root" => {
"child" => {
("lit", 3)
}
},
("sibling", 3)
};
assert_eq!(tree, expected);
Sourcepub fn close_at_with(
&mut self,
c: &Checkpoint<F::Pointer>,
data: T,
span: Span<F::Index>,
) -> Result<F::Pointer, Error<F::Error>>
pub fn close_at_with( &mut self, c: &Checkpoint<F::Pointer>, data: T, span: Span<F::Index>, ) -> Result<F::Pointer, Error<F::Error>>
Insert a node with a custom length.
§Errors
The checkpoint being closed must be a sibling. Otherwise a
Error::CloseAtError
will be raised.
This might also sporadically error with Error::MissingNode
, in case
a checkpoint is used that was constructed from another tree.
§Examples
use syntree::Span;
let mut tree = syntree::Builder::new();
let c = tree.checkpoint()?;
tree.token_with("lit", Span::new(1, 3))?;
tree.close_at_with(&c, "custom", Span::new(0, 6))?;
tree.token_with("lit2", Span::new(6, 8))?;
let tree = tree.build()?;
let root = tree.first().ok_or("missing root")?;
assert_eq!(root.value(), "custom");
assert_eq!(root.span().start, 0);
assert_eq!(root.span().end, 6);
Sourcepub fn build(self) -> Result<Tree<T, F>, Error<F::Error>>
pub fn build(self) -> Result<Tree<T, F>, Error<F::Error>>
Build a Tree from the current state of the builder.
§Errors
This requires the stack in the builder to be empty. Otherwise a
Error::BuildError
will be raised.
§Examples
let mut tree = syntree::Builder::new();
tree.open("child")?;
tree.token("number", 3)?;
tree.close()?;
tree.open("child")?;
tree.close()?;
let tree = tree.build()?;
let expected = syntree::tree! {
"child" => {
("number", 3)
},
"child" => {},
};
assert_eq!(tree, expected);
If a tree is unbalanced during construction, building will fail with an error:
use syntree::{Error, Span, Builder};
let mut tree = syntree::Builder::new();
tree.open("number")?;
tree.token("lit", 3)?;
tree.close()?;
tree.open("number")?;
// "number" is left open.
assert!(matches!(tree.build(), Err(Error::BuildError)));