syntree

Struct Builder

Source
pub struct Builder<T, F = FlavorDefault>
where T: Copy, F: Flavor,
{ /* 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,

Source

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>
where T: Copy, F: Flavor,

Source

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);
Source

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);
Source

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);
Source

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()?;
Source

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);
Source

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()?;
Source

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);
Source

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);
Source

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);
Source

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);
Source

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);
Source

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);
Source

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)));

Trait Implementations§

Source§

impl<T, F> Clone for Builder<T, F>
where T: Copy, F: Flavor<Indexes: Clone, Width: Width<Pointer: Clone>>, F::Storage<Links<T, F::Index, F::Pointer>>: Clone,

Source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T, F> Debug for Builder<T, F>
where T: Copy + Debug, F: Flavor + Debug, F::Pointer: Debug, F::Index: Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T, F> Default for Builder<T, F>
where T: Copy, F: Flavor,

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<T, F> Freeze for Builder<T, F>
where <F as Flavor>::Index: Freeze, <F as Flavor>::Storage<Links<T, <F as Flavor>::Index, <F as Flavor>::Pointer>>: Freeze, <F as Flavor>::Indexes: Freeze, <F as Flavor>::Pointer: Freeze,

§

impl<T, F = FlavorDefault> !RefUnwindSafe for Builder<T, F>

§

impl<T, F = FlavorDefault> !Send for Builder<T, F>

§

impl<T, F = FlavorDefault> !Sync for Builder<T, F>

§

impl<T, F> Unpin for Builder<T, F>
where <F as Flavor>::Index: Unpin, <F as Flavor>::Storage<Links<T, <F as Flavor>::Index, <F as Flavor>::Pointer>>: Unpin, <F as Flavor>::Indexes: Unpin, <F as Flavor>::Pointer: Unpin,

§

impl<T, F = FlavorDefault> !UnwindSafe for Builder<T, F>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.