1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
//! The "syntax tree" is a thread-local view of the green tree //! with parent pointers and text offsets. pub(self) use self::free_list::FreeList; pub use self::{ node::{Children, Node}, text::Text, token::Token, traits::Language, }; use {crate::Kind, std::fmt}; mod text; mod node; mod token; mod free_list; // NB: this module is just here to make rustdoc treat all re-exported types uniformly. // For some reason it treats re-exports ultimately from a private module differently. mod traits { use super::*; /// Specialization information for a particular language grammar. /// /// Rather than be a purely typesystem-level trait where all functions are /// associated functions, this trait's methods take `self` by reference. /// This allows dynamic interpretation of language rules for interpreters. /// For the common, statically known case, you should use a ZST impl. /// /// The language resolver must be cloneable, as all node handles have one. /// (As such, it should also be small and quickly cloneable – `Rc` level.) /// If at all possible, it should be a `Copy` handle and only `usize` big. pub trait Language: Clone { /// A typed kind to identify the kind of a node in the tree. /// /// The kind must be representable as a raw `u16`, /// but may use an arbitrarily complex encoding if desired. /// This allows you to use a different kind model /// than rowan's fully erased storage layer. type Kind: fmt::Debug; /// Turn a typed kind into a raw kind. fn kind_into_raw(&self, kind: Self::Kind) -> Kind; /// Turn a raw kind into a typed kind. fn kind_from_raw(&self, kind: Kind) -> Self::Kind; /// Determine if a node is a token. /// /// For a node to be a token, it must be backed by a `GreenToken`. /// /// By default, all `GreenToken` nodes are considered tokens. /// However, it is possible to implement delayed parsing /// by implementing this method to check the kind instead, /// and allowing non-token nodes to remain as unparsed `GreenToken` /// nodes until their content is required to be parsed. /// /// If doing this, the root node should be stored in a cell /// or similar structure to allow updating it when needed. /// [arc-swap] explains the pattern here, though it uses /// atomic reference counting instead of nonatomic. /// // NB: arc-swap actually supports `ArcSwapAny<Rc<_>>`, // but this is stronger than anyone realistically needs, // as it makes swapping the Rc atomic (when it's already // confined to one thread, so the atomic swap is unneeded). // Someone should put together an rc-swap that exposes a similar // API but uses the fact that it doesn't need to be thread-safe. // Until then `RefCell<Rc<_>>` is close enough. /// [arc-swap]: <https://docs.rs/arc-swap/> fn is_token(&self, node: &Node<Self>) -> bool { node.green().is_token() } } } /// Generic treatment of language trees. #[derive(Debug, Default, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct Generic; #[rustfmt::skip] impl Language for Generic { type Kind = Kind; fn kind_into_raw(&self, kind: Kind) -> Kind { kind } fn kind_from_raw(&self, kind: Kind) -> Kind { kind } }