//! Example that takes the input //! 1 + 2 * 3 + 4 //! and builds the tree //! - Marker(Root) //! - Marker(Operation) //! - Marker(Operation) //! - "1" Token(Number) //! - "+" Token(Add) //! - Marker(Operation) //! - "2" Token(Number) //! - "*" Token(Mul) //! - "3" Token(Number) //! - "+" Token(Add) //! - "4" Token(Number) use rowan::{GreenNodeBuilder, NodeOrToken}; use std::iter::Peekable; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[allow(non_camel_case_types)] #[repr(u16)] enum SyntaxKind { WHITESPACE = 0, ADD, SUB, MUL, DIV, NUMBER, ERROR, OPERATION, ROOT, } use SyntaxKind::*; impl From for rowan::SyntaxKind { fn from(kind: SyntaxKind) -> Self { Self(kind as u16) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] enum Lang {} impl rowan::Language for Lang { type Kind = SyntaxKind; fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind { assert!(raw.0 <= ROOT as u16); unsafe { std::mem::transmute::(raw.0) } } fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind { kind.into() } } type SyntaxNode = rowan::SyntaxNode; #[allow(unused)] type SyntaxToken = rowan::SyntaxToken; #[allow(unused)] type SyntaxElement = rowan::NodeOrToken; struct Parser> { builder: GreenNodeBuilder<'static>, iter: Peekable, } impl> Parser { fn peek(&mut self) -> Option { while self.iter.peek().map(|&(t, _)| t == WHITESPACE).unwrap_or(false) { self.bump(); } self.iter.peek().map(|&(t, _)| t) } fn bump(&mut self) { if let Some((token, string)) = self.iter.next() { self.builder.token(token.into(), string.as_str()); } } fn parse_val(&mut self) { match self.peek() { Some(NUMBER) => self.bump(), _ => { self.builder.start_node(ERROR.into()); self.bump(); self.builder.finish_node(); } } } fn handle_operation(&mut self, tokens: &[SyntaxKind], next: fn(&mut Self)) { let checkpoint = self.builder.checkpoint(); next(self); while self.peek().map(|t| tokens.contains(&t)).unwrap_or(false) { self.builder.start_node_at(checkpoint, OPERATION.into()); self.bump(); next(self); self.builder.finish_node(); } } fn parse_mul(&mut self) { self.handle_operation(&[MUL, DIV], Self::parse_val) } fn parse_add(&mut self) { self.handle_operation(&[ADD, SUB], Self::parse_mul) } fn parse(mut self) -> SyntaxNode { self.builder.start_node(ROOT.into()); self.parse_add(); self.builder.finish_node(); SyntaxNode::new_root(self.builder.finish()) } } fn print(indent: usize, element: SyntaxElement) { let kind: SyntaxKind = element.kind().into(); print!("{:indent$}", "", indent = indent); match element { NodeOrToken::Node(node) => { println!("- {:?}", kind); for child in node.children_with_tokens() { print(indent + 2, child); } } NodeOrToken::Token(token) => println!("- {:?} {:?}", token.text(), kind), } } fn main() { let ast = Parser { builder: GreenNodeBuilder::new(), iter: vec![ // 1 + 2 * 3 + 4 (NUMBER, "1".into()), (WHITESPACE, " ".into()), (ADD, "+".into()), (WHITESPACE, " ".into()), (NUMBER, "2".into()), (WHITESPACE, " ".into()), (MUL, "*".into()), (WHITESPACE, " ".into()), (NUMBER, "3".into()), (WHITESPACE, " ".into()), (ADD, "+".into()), (WHITESPACE, " ".into()), (NUMBER, "4".into()), ] .into_iter() .peekable(), } .parse(); print(0, ast.into()); }