summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parse/parser.rs29
-rw-r--r--src/syntax/mod.rs55
2 files changed, 71 insertions, 13 deletions
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 374e7c09..8c68d630 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -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> {
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> {
let len = self.children.len();
let code = self.tokens.mode() == TokenMode::Code;
@@ -172,6 +176,8 @@ impl<'s> Parser<'s> {
(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) {
let index = self.node_index_from_back(index).unwrap();
let child = std::mem::take(&mut self.children[index]);
@@ -179,6 +185,7 @@ impl<'s> Parser<'s> {
self.children[index] = item.into();
}
+ /// Eat and wrap the next token.
pub fn convert(&mut self, kind: NodeKind) {
let len = self.tokens.index() - self.next_start;
@@ -194,9 +201,11 @@ impl<'s> Parser<'s> {
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<_> =
- 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();
self.children
.push(GreenNode::with_children(kind, len, preserved).into());
@@ -219,6 +228,8 @@ impl<'s> Parser<'s> {
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 {
if !self.success {
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 {
if !self.success {
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> {
match self.children.pop().unwrap() {
Green::Node(n) => n,
@@ -263,6 +277,7 @@ impl<'s> Parser<'s> {
self.peek().is_none()
}
+ /// Consume the next token and return its kind.
fn eat_peeked(&mut self) -> Option<NodeKind> {
let token = self.peek()?.clone();
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 {
match token {
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 {
Self::skip_type_ext(token, self.stop_at_newline())
}
- /// Move to the next token.
+ /// Consume the next token.
pub fn eat(&mut self) {
self.children.push(
GreenData::new(
@@ -516,6 +534,7 @@ impl<'s> Parser<'s> {
self.fast_forward();
}
+ /// Move to the next token.
pub fn fast_forward(&mut self) {
if !self.next.as_ref().map_or(false, |x| self.skip_type(x)) {
self.prev_end = self.tokens.index().into();
@@ -567,20 +586,24 @@ impl<'s> Parser<'s> {
self.groups.iter().any(|g| g.kind == kind)
}
+ /// Returns the last child of the current stack frame.
pub fn last_child(&self) -> Option<&Green> {
self.children.last()
}
+ /// Whether the last operation was successful.
pub fn success(&mut self) -> bool {
let s = self.success;
self.success = true;
s
}
+ /// Declare the last operation as unsuccessful.
pub fn unsuccessful(&mut self) {
self.success = false;
}
+ /// Amount of children in the current stack frame.
pub fn child_count(&self) -> usize {
self.children.len()
}
diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs
index ca41d33f..61e0bb7e 100644
--- a/src/syntax/mod.rs
+++ b/src/syntax/mod.rs
@@ -30,6 +30,7 @@ pub enum Green {
}
impl Green {
+ /// Returns the metadata of the node.
fn data(&self) -> &GreenData {
match self {
Green::Node(n) => &n.data,
@@ -37,18 +38,22 @@ impl Green {
}
}
+ /// The type of the node.
pub fn kind(&self) -> &NodeKind {
self.data().kind()
}
+ /// The length of the node.
pub fn len(&self) -> usize {
self.data().len()
}
+ /// Whether the node or its children contain an error.
pub fn erroneous(&self) -> bool {
self.data().erroneous()
}
+ /// The node's children.
pub fn children(&self) -> &[Green] {
match self {
Green::Node(n) => &n.children(),
@@ -87,23 +92,19 @@ pub struct GreenNode {
}
impl GreenNode {
- pub fn new(kind: NodeKind, len: usize) -> Self {
- Self {
- data: GreenData::new(kind, len),
- children: Vec::new(),
- }
- }
-
+ /// Creates a new node with the given kind and children.
pub fn with_children(kind: NodeKind, len: usize, children: Vec<Green>) -> Self {
let mut data = GreenData::new(kind, len);
data.erroneous |= children.iter().any(|c| c.erroneous());
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 {
Self::with_children(kind, len, vec![child.into()])
}
+ /// The node's children.
pub fn children(&self) -> &[Green] {
&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)]
pub struct GreenData {
/// What kind of node this is (each kind would have its own struct in a
@@ -134,18 +135,22 @@ pub struct GreenData {
}
impl GreenData {
+ /// Create new node metadata.
pub fn new(kind: NodeKind, len: usize) -> Self {
Self { len, erroneous: kind.is_error(), kind }
}
+ /// The type of the node.
pub fn kind(&self) -> &NodeKind {
&self.kind
}
+ /// The length of the node.
pub fn len(&self) -> usize {
self.len
}
+ /// Whether the node or its children contain an error.
pub fn erroneous(&self) -> bool {
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)]
pub struct RedRef<'a> {
id: SourceId,
@@ -165,6 +172,7 @@ pub struct RedRef<'a> {
}
impl<'a> RedRef<'a> {
+ /// Convert to an owned representation.
pub fn own(self) -> RedNode {
RedNode {
id: self.id,
@@ -173,18 +181,22 @@ impl<'a> RedRef<'a> {
}
}
+ /// The type of the node.
pub fn kind(&self) -> &NodeKind {
self.green.kind()
}
+ /// The span of the node.
pub fn span(&self) -> Span {
Span::new(self.id, self.offset, self.offset + self.green.len())
}
+ /// The length of the node.
pub fn len(&self) -> usize {
self.green.len()
}
+ /// Convert the node to a typed AST node.
pub fn cast<T>(self) -> Option<T>
where
T: TypedNode,
@@ -192,10 +204,12 @@ impl<'a> RedRef<'a> {
T::cast_from(self)
}
+ /// Whether the node or its children contain an error.
pub fn erroneous(&self) -> bool {
self.green.erroneous()
}
+ /// The node's children.
pub fn children(self) -> impl Iterator<Item = RedRef<'a>> + Clone {
let children = match &self.green {
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> {
if !self.green.erroneous() {
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> {
self.children()
.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> {
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> {
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)]
pub struct RedNode {
id: SourceId,
@@ -267,10 +287,12 @@ pub struct RedNode {
}
impl RedNode {
+ /// Create a new root node from a [`GreenNode`].
pub fn new_root(root: Rc<GreenNode>, id: SourceId) -> Self {
Self { id, offset: 0, green: root.into() }
}
+ /// Convert to a borrowed representation.
pub fn as_ref<'a>(&'a self) -> RedRef<'a> {
RedRef {
id: self.id,
@@ -279,14 +301,17 @@ impl RedNode {
}
}
+ /// The span of the node.
pub fn span(&self) -> Span {
self.as_ref().span()
}
+ /// The length of the node.
pub fn len(&self) -> usize {
self.as_ref().len()
}
+ /// Convert the node to a typed AST node.
pub fn cast<T>(self) -> Option<T>
where
T: TypedNode,
@@ -294,26 +319,32 @@ impl RedNode {
T::cast_from(self.as_ref())
}
+ /// The type of the node.
pub fn kind(&self) -> &NodeKind {
self.green.kind()
}
+ /// The children of the node.
pub fn children<'a>(&'a self) -> impl Iterator<Item = RedRef<'a>> + Clone {
self.as_ref().children()
}
+ /// The error messages for this node and its descendants.
pub fn errors<'a>(&'a self) -> Vec<Error> {
self.as_ref().errors()
}
+ /// Get the first child of some type.
pub(crate) fn typed_child(&self, kind: &NodeKind) -> Option<RedNode> {
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> {
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> {
self.as_ref().cast_last_child()
}
@@ -477,7 +508,7 @@ pub enum NodeKind {
/// A percentage: `50%`.
///
/// _Note_: `50%` is stored as `50.0` here, as in the corresponding
- /// [literal](super::Lit::Percent).
+ /// [literal](Lit::Percent).
Percentage(f64),
/// A fraction unit: `3fr`.
Fraction(f64),
@@ -595,6 +626,7 @@ impl Display for NodeKind {
}
impl NodeKind {
+ /// Whether this is some kind of parenthesis.
pub fn is_paren(&self) -> bool {
match self {
Self::LeftParen => true,
@@ -603,6 +635,7 @@ impl NodeKind {
}
}
+ /// Whether this is some kind of bracket.
pub fn is_bracket(&self) -> bool {
match self {
Self::LeftBracket => true,
@@ -611,6 +644,7 @@ impl NodeKind {
}
}
+ /// Whether this is some kind of brace.
pub fn is_brace(&self) -> bool {
match self {
Self::LeftBrace => true,
@@ -619,8 +653,9 @@ impl NodeKind {
}
}
+ /// Whether this is some kind of error.
pub fn is_error(&self) -> bool {
- matches!(self, NodeKind::Error(_, _))
+ matches!(self, NodeKind::Error(_, _) | NodeKind::Unknown(_))
}
pub fn as_str(&self) -> &'static str {