use std::fmt;
use crate::span::Span;
use crate::token::{Token, TokenKind};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum NodeKind {
File,
Error,
Import,
Struct,
Field,
TypeDecl,
Variant,
FnDecl,
ParamList,
Param,
Let,
Body,
Attr,
AttrPath,
Block,
Include,
IfStmt,
ForStmt,
Literal,
Str,
Interp,
Name,
Symbol,
SelfExpr,
List,
ListComp,
Map,
MapEntry,
MapComp,
StructLit,
Paren,
Call,
ArgList,
Arg,
FieldExpr,
IndexExpr,
BinaryExpr,
UnaryExpr,
IfExpr,
MatchExpr,
MatchArm,
LetExpr,
Binding,
Lambda,
PartExpr,
TypePath,
NamedType,
TypeArgList,
FnType,
RefinedType,
RangePredicate,
NamedPredicate,
WildcardPat,
LiteralPat,
NamePat,
VariantPat,
FieldPat,
OrPat,
}
#[derive(Debug, Clone)]
pub struct SyntaxTree {
source: Box<str>,
tokens: Vec<Token>,
token_parents: Vec<usize>,
nodes: Vec<NodeData>,
elements: Vec<Element>,
root: usize,
}
#[derive(Debug, Clone)]
struct NodeData {
kind: NodeKind,
span: Span,
parent: Option<usize>,
first_child: usize,
child_count: usize,
}
#[derive(Debug, Clone, Copy)]
enum Element {
Node(usize),
Token(usize),
}
impl SyntaxTree {
pub fn root(&self) -> SyntaxNode<'_> {
SyntaxNode {
tree: self,
index: self.root,
}
}
pub(crate) fn node_count(&self) -> usize {
self.nodes.len()
}
pub(crate) fn node(&self, index: usize) -> Option<SyntaxNode<'_>> {
(index < self.nodes.len()).then_some(SyntaxNode { tree: self, index })
}
fn element(&self, element: Element) -> SyntaxElement<'_> {
match element {
Element::Node(index) => SyntaxElement::Node(SyntaxNode { tree: self, index }),
Element::Token(index) => SyntaxElement::Token(SyntaxToken { tree: self, index }),
}
}
}
#[derive(Clone, Copy)]
pub struct SyntaxNode<'a> {
tree: &'a SyntaxTree,
index: usize,
}
impl<'a> SyntaxNode<'a> {
pub fn kind(self) -> NodeKind {
self.data().kind
}
pub fn span(self) -> Span {
self.data().span
}
pub fn text(self) -> &'a str {
&self.tree.source[self.span().range()]
}
pub fn parent(self) -> Option<SyntaxNode<'a>> {
let tree = self.tree;
self.data().parent.map(|index| SyntaxNode { tree, index })
}
pub fn children(self) -> impl Iterator<Item = SyntaxNode<'a>> {
self.children_with_tokens()
.filter_map(|element| match element {
SyntaxElement::Node(node) => Some(node),
SyntaxElement::Token(_) => None,
})
}
pub fn children_with_tokens(self) -> impl Iterator<Item = SyntaxElement<'a>> {
let tree = self.tree;
let data = self.data();
tree.elements[data.first_child..data.first_child + data.child_count]
.iter()
.map(move |&element| tree.element(element))
}
pub(crate) fn index(self) -> usize {
self.index
}
fn data(self) -> &'a NodeData {
&self.tree.nodes[self.index]
}
}
impl fmt::Debug for SyntaxNode<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let span = self.span();
write!(f, "{:?}@{}..{}", self.kind(), span.start, span.end)
}
}
impl fmt::Display for SyntaxNode<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.text())
}
}
#[derive(Clone, Copy)]
pub struct SyntaxToken<'a> {
tree: &'a SyntaxTree,
index: usize,
}
impl<'a> SyntaxToken<'a> {
pub fn kind(self) -> TokenKind {
self.tree.tokens[self.index].kind
}
pub fn span(self) -> Span {
self.tree.tokens[self.index].span
}
pub fn text(self) -> &'a str {
&self.tree.source[self.span().range()]
}
pub fn parent(self) -> SyntaxNode<'a> {
SyntaxNode {
tree: self.tree,
index: self.tree.token_parents[self.index],
}
}
}
impl fmt::Debug for SyntaxToken<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let span = self.span();
write!(
f,
"{:?}@{}..{} {:?}",
self.kind(),
span.start,
span.end,
self.text()
)
}
}
impl fmt::Display for SyntaxToken<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.text())
}
}
#[derive(Debug, Clone, Copy)]
pub enum SyntaxElement<'a> {
Node(SyntaxNode<'a>),
Token(SyntaxToken<'a>),
}
impl<'a> SyntaxElement<'a> {
pub fn span(self) -> Span {
match self {
Self::Node(node) => node.span(),
Self::Token(token) => token.span(),
}
}
pub fn text(self) -> &'a str {
match self {
Self::Node(node) => node.text(),
Self::Token(token) => token.text(),
}
}
}
pub(crate) struct Builder {
nodes: Vec<NodeData>,
elements: Vec<Element>,
token_parents: Vec<usize>,
pending: Vec<Element>,
open: Vec<(NodeKind, usize)>,
}
impl Builder {
pub(crate) fn new(token_count: usize) -> Self {
Self {
nodes: Vec::new(),
elements: Vec::with_capacity(token_count),
token_parents: vec![0; token_count],
pending: Vec::new(),
open: Vec::new(),
}
}
pub(crate) fn start_node(&mut self, kind: NodeKind) {
self.open.push((kind, self.pending.len()));
}
pub(crate) fn checkpoint(&self) -> usize {
self.pending.len()
}
pub(crate) fn start_node_at(&mut self, checkpoint: usize, kind: NodeKind) {
self.open.push((kind, checkpoint.min(self.pending.len())));
}
pub(crate) fn token(&mut self, index: usize) {
self.pending.push(Element::Token(index));
}
pub(crate) fn finish_node(&mut self, tokens: &[Token], empty_at: usize) {
let Some((kind, first)) = self.open.pop() else {
return;
};
let index = self.nodes.len();
let first_child = self.elements.len();
let mut span: Option<Span> = None;
for element in self.pending.drain(first..) {
let child_span = match element {
Element::Node(child) => {
self.nodes[child].parent = Some(index);
self.nodes[child].span
}
Element::Token(token) => {
self.token_parents[token] = index;
tokens[token].span
}
};
span = Some(match span {
Some(span) => Span {
start: span.start,
end: child_span.end,
},
None => child_span,
});
self.elements.push(element);
}
self.nodes.push(NodeData {
kind,
span: span.unwrap_or(Span {
start: empty_at,
end: empty_at,
}),
parent: None,
first_child,
child_count: self.elements.len() - first_child,
});
self.pending.push(Element::Node(index));
}
pub(crate) fn finish(mut self, source: &str, tokens: Vec<Token>) -> SyntaxTree {
let root = self
.nodes
.len()
.checked_sub(1)
.expect("the root node is finished before the tree");
self.nodes[root].span = Span {
start: 0,
end: source.len(),
};
SyntaxTree {
root,
source: source.into(),
tokens,
token_parents: self.token_parents,
nodes: self.nodes,
elements: self.elements,
}
}
}