Add documentation

This commit is contained in:
Martin Haug 2021-11-01 13:45:33 +01:00
parent 49fb3cd4e2
commit 42afb27cef
2 changed files with 71 additions and 13 deletions

View File

@ -112,10 +112,14 @@ impl<'s> Parser<'s> {
} }
} }
/// Return the a child from the current stack frame specified by its
/// non-trivia index from the back.
pub fn child(&self, child: usize) -> Option<&Green> { pub fn child(&self, child: usize) -> Option<&Green> {
self.node_index_from_back(child).map(|i| &self.children[i]) self.node_index_from_back(child).map(|i| &self.children[i])
} }
/// Map a non-trivia index from the back of the current stack frame to a
/// normal index.
fn node_index_from_back(&self, child: usize) -> Option<usize> { fn node_index_from_back(&self, child: usize) -> Option<usize> {
let len = self.children.len(); let len = self.children.len();
let code = self.tokens.mode() == TokenMode::Code; let code = self.tokens.mode() == TokenMode::Code;
@ -172,6 +176,8 @@ impl<'s> Parser<'s> {
(stack_offset, diff) (stack_offset, diff)
} }
/// Wrap a specified node in the current stack frame (indexed from the back,
/// not including trivia).
pub fn wrap(&mut self, index: usize, kind: NodeKind) { pub fn wrap(&mut self, index: usize, kind: NodeKind) {
let index = self.node_index_from_back(index).unwrap(); let index = self.node_index_from_back(index).unwrap();
let child = std::mem::take(&mut self.children[index]); let child = std::mem::take(&mut self.children[index]);
@ -179,6 +185,7 @@ impl<'s> Parser<'s> {
self.children[index] = item.into(); self.children[index] = item.into();
} }
/// Eat and wrap the next token.
pub fn convert(&mut self, kind: NodeKind) { pub fn convert(&mut self, kind: NodeKind) {
let len = self.tokens.index() - self.next_start; let len = self.tokens.index() - self.next_start;
@ -194,9 +201,11 @@ impl<'s> Parser<'s> {
self.success = true; self.success = true;
} }
pub fn convert_with(&mut self, preserve: usize, kind: NodeKind) { /// Wrap the last `amount` children in the current stack frame with a new
/// node.
pub fn convert_with(&mut self, amount: usize, kind: NodeKind) {
let preserved: Vec<_> = let preserved: Vec<_> =
self.children.drain(self.children.len() - preserve ..).collect(); self.children.drain(self.children.len() - amount ..).collect();
let len = preserved.iter().map(|c| c.len()).sum(); let len = preserved.iter().map(|c| c.len()).sum();
self.children self.children
.push(GreenNode::with_children(kind, len, preserved).into()); .push(GreenNode::with_children(kind, len, preserved).into());
@ -219,6 +228,8 @@ impl<'s> Parser<'s> {
self.success = false; self.success = false;
} }
/// This function [`Self::lift`]s if the last operation was unsuccessful and
/// returns whether it did.
pub fn may_lift_abort(&mut self) -> bool { pub fn may_lift_abort(&mut self) -> bool {
if !self.success { if !self.success {
self.lift(); self.lift();
@ -229,6 +240,8 @@ impl<'s> Parser<'s> {
} }
} }
/// This function [`Self::end`]s if the last operation was unsuccessful and
/// returns whether it did.
pub fn may_end_abort(&mut self, kind: NodeKind) -> bool { pub fn may_end_abort(&mut self, kind: NodeKind) -> bool {
if !self.success { if !self.success {
self.end(kind); self.end(kind);
@ -251,6 +264,7 @@ impl<'s> Parser<'s> {
} }
} }
/// End the parsing process and return the last child.
pub fn finish(&mut self) -> Rc<GreenNode> { pub fn finish(&mut self) -> Rc<GreenNode> {
match self.children.pop().unwrap() { match self.children.pop().unwrap() {
Green::Node(n) => n, Green::Node(n) => n,
@ -263,6 +277,7 @@ impl<'s> Parser<'s> {
self.peek().is_none() self.peek().is_none()
} }
/// Consume the next token and return its kind.
fn eat_peeked(&mut self) -> Option<NodeKind> { fn eat_peeked(&mut self) -> Option<NodeKind> {
let token = self.peek()?.clone(); let token = self.peek()?.clone();
self.eat(); self.eat();
@ -490,6 +505,8 @@ impl<'s> Parser<'s> {
} }
} }
/// Returns whether the given type can be skipped over given the current
/// newline mode.
pub fn skip_type_ext(token: &NodeKind, stop_at_newline: bool) -> bool { pub fn skip_type_ext(token: &NodeKind, stop_at_newline: bool) -> bool {
match token { match token {
NodeKind::Space(n) => n < &1 || !stop_at_newline, NodeKind::Space(n) => n < &1 || !stop_at_newline,
@ -499,11 +516,12 @@ impl<'s> Parser<'s> {
} }
} }
/// Returns whether the given type can be skipped over.
fn skip_type(&self, token: &NodeKind) -> bool { fn skip_type(&self, token: &NodeKind) -> bool {
Self::skip_type_ext(token, self.stop_at_newline()) Self::skip_type_ext(token, self.stop_at_newline())
} }
/// Move to the next token. /// Consume the next token.
pub fn eat(&mut self) { pub fn eat(&mut self) {
self.children.push( self.children.push(
GreenData::new( GreenData::new(
@ -516,6 +534,7 @@ impl<'s> Parser<'s> {
self.fast_forward(); self.fast_forward();
} }
/// Move to the next token.
pub fn fast_forward(&mut self) { pub fn fast_forward(&mut self) {
if !self.next.as_ref().map_or(false, |x| self.skip_type(x)) { if !self.next.as_ref().map_or(false, |x| self.skip_type(x)) {
self.prev_end = self.tokens.index().into(); self.prev_end = self.tokens.index().into();
@ -567,20 +586,24 @@ impl<'s> Parser<'s> {
self.groups.iter().any(|g| g.kind == kind) self.groups.iter().any(|g| g.kind == kind)
} }
/// Returns the last child of the current stack frame.
pub fn last_child(&self) -> Option<&Green> { pub fn last_child(&self) -> Option<&Green> {
self.children.last() self.children.last()
} }
/// Whether the last operation was successful.
pub fn success(&mut self) -> bool { pub fn success(&mut self) -> bool {
let s = self.success; let s = self.success;
self.success = true; self.success = true;
s s
} }
/// Declare the last operation as unsuccessful.
pub fn unsuccessful(&mut self) { pub fn unsuccessful(&mut self) {
self.success = false; self.success = false;
} }
/// Amount of children in the current stack frame.
pub fn child_count(&self) -> usize { pub fn child_count(&self) -> usize {
self.children.len() self.children.len()
} }

View File

@ -30,6 +30,7 @@ pub enum Green {
} }
impl Green { impl Green {
/// Returns the metadata of the node.
fn data(&self) -> &GreenData { fn data(&self) -> &GreenData {
match self { match self {
Green::Node(n) => &n.data, Green::Node(n) => &n.data,
@ -37,18 +38,22 @@ impl Green {
} }
} }
/// The type of the node.
pub fn kind(&self) -> &NodeKind { pub fn kind(&self) -> &NodeKind {
self.data().kind() self.data().kind()
} }
/// The length of the node.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.data().len() self.data().len()
} }
/// Whether the node or its children contain an error.
pub fn erroneous(&self) -> bool { pub fn erroneous(&self) -> bool {
self.data().erroneous() self.data().erroneous()
} }
/// The node's children.
pub fn children(&self) -> &[Green] { pub fn children(&self) -> &[Green] {
match self { match self {
Green::Node(n) => &n.children(), Green::Node(n) => &n.children(),
@ -87,23 +92,19 @@ pub struct GreenNode {
} }
impl GreenNode { impl GreenNode {
pub fn new(kind: NodeKind, len: usize) -> Self { /// Creates a new node with the given kind and children.
Self {
data: GreenData::new(kind, len),
children: Vec::new(),
}
}
pub fn with_children(kind: NodeKind, len: usize, children: Vec<Green>) -> Self { pub fn with_children(kind: NodeKind, len: usize, children: Vec<Green>) -> Self {
let mut data = GreenData::new(kind, len); let mut data = GreenData::new(kind, len);
data.erroneous |= children.iter().any(|c| c.erroneous()); data.erroneous |= children.iter().any(|c| c.erroneous());
Self { data, children } Self { data, children }
} }
/// Creates a new node with the given kind and a single child.
pub fn with_child(kind: NodeKind, len: usize, child: impl Into<Green>) -> Self { pub fn with_child(kind: NodeKind, len: usize, child: impl Into<Green>) -> Self {
Self::with_children(kind, len, vec![child.into()]) Self::with_children(kind, len, vec![child.into()])
} }
/// The node's children.
pub fn children(&self) -> &[Green] { pub fn children(&self) -> &[Green] {
&self.children &self.children
} }
@ -121,7 +122,7 @@ impl From<Rc<GreenNode>> for Green {
} }
} }
/// Data shared between [`GreenNode`]s and [`GreenToken`]s. /// Data shared between [`GreenNode`]s and leaf nodes.
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct GreenData { pub struct GreenData {
/// What kind of node this is (each kind would have its own struct in a /// What kind of node this is (each kind would have its own struct in a
@ -134,18 +135,22 @@ pub struct GreenData {
} }
impl GreenData { impl GreenData {
/// Create new node metadata.
pub fn new(kind: NodeKind, len: usize) -> Self { pub fn new(kind: NodeKind, len: usize) -> Self {
Self { len, erroneous: kind.is_error(), kind } Self { len, erroneous: kind.is_error(), kind }
} }
/// The type of the node.
pub fn kind(&self) -> &NodeKind { pub fn kind(&self) -> &NodeKind {
&self.kind &self.kind
} }
/// The length of the node.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.len self.len
} }
/// Whether the node or its children contain an error.
pub fn erroneous(&self) -> bool { pub fn erroneous(&self) -> bool {
self.erroneous self.erroneous
} }
@ -157,6 +162,8 @@ impl From<GreenData> for Green {
} }
} }
/// A borrowed wrapper for the [`GreenNode`] type that allows to access spans,
/// error lists and cast to an AST.
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
pub struct RedRef<'a> { pub struct RedRef<'a> {
id: SourceId, id: SourceId,
@ -165,6 +172,7 @@ pub struct RedRef<'a> {
} }
impl<'a> RedRef<'a> { impl<'a> RedRef<'a> {
/// Convert to an owned representation.
pub fn own(self) -> RedNode { pub fn own(self) -> RedNode {
RedNode { RedNode {
id: self.id, id: self.id,
@ -173,18 +181,22 @@ impl<'a> RedRef<'a> {
} }
} }
/// The type of the node.
pub fn kind(&self) -> &NodeKind { pub fn kind(&self) -> &NodeKind {
self.green.kind() self.green.kind()
} }
/// The span of the node.
pub fn span(&self) -> Span { pub fn span(&self) -> Span {
Span::new(self.id, self.offset, self.offset + self.green.len()) Span::new(self.id, self.offset, self.offset + self.green.len())
} }
/// The length of the node.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.green.len() self.green.len()
} }
/// Convert the node to a typed AST node.
pub fn cast<T>(self) -> Option<T> pub fn cast<T>(self) -> Option<T>
where where
T: TypedNode, T: TypedNode,
@ -192,10 +204,12 @@ impl<'a> RedRef<'a> {
T::cast_from(self) T::cast_from(self)
} }
/// Whether the node or its children contain an error.
pub fn erroneous(&self) -> bool { pub fn erroneous(&self) -> bool {
self.green.erroneous() self.green.erroneous()
} }
/// The node's children.
pub fn children(self) -> impl Iterator<Item = RedRef<'a>> + Clone { pub fn children(self) -> impl Iterator<Item = RedRef<'a>> + Clone {
let children = match &self.green { let children = match &self.green {
Green::Node(node) => node.children(), Green::Node(node) => node.children(),
@ -210,6 +224,7 @@ impl<'a> RedRef<'a> {
}) })
} }
/// The error messages for this node and its descendants.
pub fn errors(&self) -> Vec<Error> { pub fn errors(&self) -> Vec<Error> {
if !self.green.erroneous() { if !self.green.erroneous() {
return vec![]; return vec![];
@ -233,15 +248,18 @@ impl<'a> RedRef<'a> {
} }
} }
/// Get the first child of some type.
pub(crate) fn typed_child(&self, kind: &NodeKind) -> Option<RedRef> { pub(crate) fn typed_child(&self, kind: &NodeKind) -> Option<RedRef> {
self.children() self.children()
.find(|x| mem::discriminant(x.kind()) == mem::discriminant(kind)) .find(|x| mem::discriminant(x.kind()) == mem::discriminant(kind))
} }
/// Get the first child that can cast to some AST type.
pub(crate) fn cast_first_child<T: TypedNode>(&self) -> Option<T> { pub(crate) fn cast_first_child<T: TypedNode>(&self) -> Option<T> {
self.children().find_map(RedRef::cast) self.children().find_map(RedRef::cast)
} }
/// Get the last child that can cast to some AST type.
pub(crate) fn cast_last_child<T: TypedNode>(&self) -> Option<T> { pub(crate) fn cast_last_child<T: TypedNode>(&self) -> Option<T> {
self.children().filter_map(RedRef::cast).last() self.children().filter_map(RedRef::cast).last()
} }
@ -259,6 +277,8 @@ impl Debug for RedRef<'_> {
} }
} }
/// An owned wrapper for the [`GreenNode`] type that allows to access spans,
/// error lists and cast to an AST.
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct RedNode { pub struct RedNode {
id: SourceId, id: SourceId,
@ -267,10 +287,12 @@ pub struct RedNode {
} }
impl RedNode { impl RedNode {
/// Create a new root node from a [`GreenNode`].
pub fn new_root(root: Rc<GreenNode>, id: SourceId) -> Self { pub fn new_root(root: Rc<GreenNode>, id: SourceId) -> Self {
Self { id, offset: 0, green: root.into() } Self { id, offset: 0, green: root.into() }
} }
/// Convert to a borrowed representation.
pub fn as_ref<'a>(&'a self) -> RedRef<'a> { pub fn as_ref<'a>(&'a self) -> RedRef<'a> {
RedRef { RedRef {
id: self.id, id: self.id,
@ -279,14 +301,17 @@ impl RedNode {
} }
} }
/// The span of the node.
pub fn span(&self) -> Span { pub fn span(&self) -> Span {
self.as_ref().span() self.as_ref().span()
} }
/// The length of the node.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.as_ref().len() self.as_ref().len()
} }
/// Convert the node to a typed AST node.
pub fn cast<T>(self) -> Option<T> pub fn cast<T>(self) -> Option<T>
where where
T: TypedNode, T: TypedNode,
@ -294,26 +319,32 @@ impl RedNode {
T::cast_from(self.as_ref()) T::cast_from(self.as_ref())
} }
/// The type of the node.
pub fn kind(&self) -> &NodeKind { pub fn kind(&self) -> &NodeKind {
self.green.kind() self.green.kind()
} }
/// The children of the node.
pub fn children<'a>(&'a self) -> impl Iterator<Item = RedRef<'a>> + Clone { pub fn children<'a>(&'a self) -> impl Iterator<Item = RedRef<'a>> + Clone {
self.as_ref().children() self.as_ref().children()
} }
/// The error messages for this node and its descendants.
pub fn errors<'a>(&'a self) -> Vec<Error> { pub fn errors<'a>(&'a self) -> Vec<Error> {
self.as_ref().errors() self.as_ref().errors()
} }
/// Get the first child of some type.
pub(crate) fn typed_child(&self, kind: &NodeKind) -> Option<RedNode> { pub(crate) fn typed_child(&self, kind: &NodeKind) -> Option<RedNode> {
self.as_ref().typed_child(kind).map(RedRef::own) self.as_ref().typed_child(kind).map(RedRef::own)
} }
/// Get the first child that can cast to some AST type.
pub(crate) fn cast_first_child<T: TypedNode>(&self) -> Option<T> { pub(crate) fn cast_first_child<T: TypedNode>(&self) -> Option<T> {
self.as_ref().cast_first_child() self.as_ref().cast_first_child()
} }
/// Get the last child that can cast to some AST type.
pub(crate) fn cast_last_child<T: TypedNode>(&self) -> Option<T> { pub(crate) fn cast_last_child<T: TypedNode>(&self) -> Option<T> {
self.as_ref().cast_last_child() self.as_ref().cast_last_child()
} }
@ -477,7 +508,7 @@ pub enum NodeKind {
/// A percentage: `50%`. /// A percentage: `50%`.
/// ///
/// _Note_: `50%` is stored as `50.0` here, as in the corresponding /// _Note_: `50%` is stored as `50.0` here, as in the corresponding
/// [literal](super::Lit::Percent). /// [literal](Lit::Percent).
Percentage(f64), Percentage(f64),
/// A fraction unit: `3fr`. /// A fraction unit: `3fr`.
Fraction(f64), Fraction(f64),
@ -595,6 +626,7 @@ impl Display for NodeKind {
} }
impl NodeKind { impl NodeKind {
/// Whether this is some kind of parenthesis.
pub fn is_paren(&self) -> bool { pub fn is_paren(&self) -> bool {
match self { match self {
Self::LeftParen => true, Self::LeftParen => true,
@ -603,6 +635,7 @@ impl NodeKind {
} }
} }
/// Whether this is some kind of bracket.
pub fn is_bracket(&self) -> bool { pub fn is_bracket(&self) -> bool {
match self { match self {
Self::LeftBracket => true, Self::LeftBracket => true,
@ -611,6 +644,7 @@ impl NodeKind {
} }
} }
/// Whether this is some kind of brace.
pub fn is_brace(&self) -> bool { pub fn is_brace(&self) -> bool {
match self { match self {
Self::LeftBrace => true, Self::LeftBrace => true,
@ -619,8 +653,9 @@ impl NodeKind {
} }
} }
/// Whether this is some kind of error.
pub fn is_error(&self) -> bool { pub fn is_error(&self) -> bool {
matches!(self, NodeKind::Error(_, _)) matches!(self, NodeKind::Error(_, _) | NodeKind::Unknown(_))
} }
pub fn as_str(&self) -> &'static str { pub fn as_str(&self) -> &'static str {