168 lines
2.9 KiB
Rust
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();
|
|
}
|
|
}
|