atelier/bake/lib/syn/cst.rs
2025-01-16 20:05:09 -05:00

168 lines
2.9 KiB
Rust

use super::{
ast,
tok::{Token, TokenKind, Tokens},
};
#[derive(Debug)]
pub struct Tree {
nodes: Vec<Node>,
}
impl Tree {
pub fn new() -> Self {
let mut out = Self { nodes: vec![] };
out.register({
let mut node = Node::unregistered();
node.kind = NodeKind::Root;
node
});
out
}
pub fn register(&mut self, mut node: Node) -> NodeRef {
node.id = self.nodes.len();
let out = NodeRef(node.id);
self.nodes.push(node);
out
}
pub fn root(&self) -> NodeRef {
NodeRef(0)
}
pub fn add_child(&mut self, parent: NodeRef, child: NodeRef) {
parent.resolve_mut(self).children.push(child);
child.resolve_mut(self).parent = Some(parent);
}
pub fn nth_child(
&self,
parent: NodeRef,
child_index: usize,
) -> Option<NodeRef> {
parent.resolve(self).children.get(child_index).copied()
}
pub fn children_of(
&self,
parent: NodeRef,
) -> impl Iterator<Item = NodeRef> {
parent.resolve(self).children.iter().copied()
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
struct NodeRef(usize);
impl NodeRef {
fn resolve<'a>(&self, tree: &'a Tree) -> &'a Node {
&tree.nodes[self.0]
}
fn resolve_mut<'a>(&self, tree: &'a mut Tree) -> &'a mut Node {
&mut tree.nodes[self.0]
}
}
#[derive(Default, Debug)]
pub struct Node {
id: usize,
parent: Option<NodeRef>,
children: Vec<NodeRef>,
kind: NodeKind,
whitespace: Option<Token>,
token: Option<Token>,
}
impl Node {
fn unregistered() -> Self {
Self {
id: usize::MAX,
parent: None,
children: vec![],
kind: NodeKind::Unknown,
whitespace: None,
token: None,
}
}
pub fn kind(&self) -> &NodeKind {
&self.kind
}
pub fn token(&self) -> Option<&Token> {
self.token.as_ref()
}
}
#[derive(Default, Debug, Eq, PartialEq)]
pub enum NodeKind {
#[default]
Unknown,
List,
Token,
Atom,
Root,
}
pub fn parse(corpus: &str) -> Tree {
let mut tree = Tree::new();
let mut tokens = Tokens::new(corpus);
while let Some(nr) = parse_one(&mut tree, &mut tokens) {
let root = tree.root();
tree.add_child(root, nr);
}
tree
}
pub fn parse_one(tree: &mut Tree, tokens: &mut Tokens) -> Option<NodeRef> {
let tok = tokens.next()?;
let (ws, tok) = match tok.kind {
TokenKind::Whitespace(_) => (Some(tok), tokens.next()),
_ => (None, Some(tok)),
};
let mut node = Node::unregistered();
node.whitespace = ws;
let tok = match tok {
Some(tok) => tok,
None => {
node.kind = NodeKind::Token;
return Some(tree.register(node));
},
};
match &tok.kind {
TokenKind::Atom(_) => {
node.kind = NodeKind::Atom;
},
_ => todo!(),
}
node.token = Some(tok);
Some(tree.register(node))
}
#[cfg(test)]
mod test {
use crate::syn::{
cst::NodeKind,
tok::{Atom, TokenKind},
};
use super::parse;
#[test]
fn atom1() {
let tree = parse("32");
let mut children =
tree.children_of(tree.root()).map(|n| n.resolve(&tree));
let first = children.next().unwrap().as_atom().unwrap().value();
}
}