use std::{
fmt::{self, Debug, Formatter},
ops::ControlFlow,
};
use crate::source::Span;
use super::origin;
pub trait Node {
const TRANSPARENT: bool = false;
fn accept<'a, V: Visit>(&'a self, visit: &'a mut V) -> ControlFlow<V::Break>;
fn trans<'a, V: Visit>(&'a self, visit: &'a mut V) -> ControlFlow<V::Break> {
if Self::TRANSPARENT {
self.accept(visit)
} else {
visit.node(self)
}
}
fn span(&self) -> Span {
let mut visit = SpanVisit(Span::INVALID);
let _ = self.accept(&mut visit);
visit.0
}
fn kind(&self) -> NodeKind;
}
struct SpanVisit(Span);
impl Visit for SpanVisit {
type Break = ();
fn node<T: Node + ?Sized>(&mut self, node: &T) -> ControlFlow<Self::Break> {
self.0 = self.0 | node.span();
ControlFlow::Continue(())
}
fn token(
&mut self,
_leaf: Token,
span: Span,
_origin: Option<origin::Id>,
) -> ControlFlow<Self::Break> {
self.0 = self.0 | span;
ControlFlow::Continue(())
}
}
#[derive(Copy, Clone, Debug)]
pub enum Token {
Comment,
Constant,
Delim,
Escape,
Field,
Key,
ModuleName,
ModuleItem,
Keyword,
Literal,
Number,
Operator,
StringDelim,
Variable,
Sigil,
}
pub trait Visit {
type Break;
fn node<T: Node + ?Sized>(&mut self, node: &T) -> ControlFlow<Self::Break>;
fn token(
&mut self,
token: Token,
span: Span,
origin: Option<origin::Id>,
) -> ControlFlow<Self::Break>;
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum NodeKind {
Literal,
Ident,
I64,
VerbatimI64,
F64,
VerbatimF64,
Bool,
Nil,
Sym,
Concat,
Escape,
BinConcat,
EscapeByte,
Group,
Unary,
Binary,
Call,
Lambda,
Field,
Index,
Array,
Dict,
Error,
Assign,
Bind,
Break,
Class,
Continue,
Def,
For,
If,
Import,
Let,
Return,
Throw,
Try,
While,
NlGuard,
Param,
Block,
Function,
ImportItem,
Branch,
Catch,
Expand,
Pair,
Body,
Pattern,
Key,
}
impl fmt::Display for NodeKind {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(self, f)
}
}