extern crate rowan;
use rowan::{GreenNodeBuilder, SmolStr};
use std::iter::Peekable;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum Token {
Whitespace,
Add,
Sub,
Mul,
Div,
Number,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum ASTKind {
Error,
Operation,
Root,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum NodeType {
Marker(ASTKind),
Token(Token),
}
struct Types;
impl rowan::Types for Types {
type Kind = NodeType;
type RootData = ();
}
type Node = rowan::SyntaxNode<Types>;
type TreeArc<T> = rowan::TreeArc<Types, T>;
struct Parser<I: Iterator<Item = (Token, SmolStr)>> {
builder: GreenNodeBuilder<Types>,
iter: Peekable<I>,
}
impl<I: Iterator<Item = (Token, SmolStr)>> Parser<I> {
fn peek(&mut self) -> Option<Token> {
while self
.iter
.peek()
.map(|&(t, _)| t == Token::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.leaf(NodeType::Token(token), string);
}
}
fn parse_val(&mut self) {
match self.peek() {
Some(Token::Number) => self.bump(),
_ => {
self.builder
.start_internal(NodeType::Marker(ASTKind::Error));
self.bump();
self.builder.finish_internal();
}
}
}
fn handle_operation(&mut self, tokens: &[Token], 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_internal_at(checkpoint, NodeType::Marker(ASTKind::Operation));
self.bump();
next(self);
self.builder.finish_internal();
}
}
fn parse_mul(&mut self) {
self.handle_operation(&[Token::Mul, Token::Div], Self::parse_val)
}
fn parse_add(&mut self) {
self.handle_operation(&[Token::Add, Token::Sub], Self::parse_mul)
}
fn parse(mut self) -> TreeArc<Node> {
self.builder.start_internal(NodeType::Marker(ASTKind::Root));
self.parse_add();
self.builder.finish_internal();
Node::new(self.builder.finish(), ())
}
}
fn print(indent: usize, node: &Node) {
print!("{:indent$}", "", indent = indent);
if let Some(text) = node.leaf_text() {
println!("- {:?} {:?}", text, node.kind());
} else {
println!("- {:?}", node.kind());
}
for child in node.children() {
print(indent + 2, child);
}
}
fn main() {
let ast = Parser {
builder: GreenNodeBuilder::new(),
iter: vec![
(Token::Number, "1".into()),
(Token::Whitespace, " ".into()),
(Token::Add, "+".into()),
(Token::Whitespace, " ".into()),
(Token::Number, "2".into()),
(Token::Whitespace, " ".into()),
(Token::Mul, "*".into()),
(Token::Whitespace, " ".into()),
(Token::Number, "3".into()),
(Token::Whitespace, " ".into()),
(Token::Add, "+".into()),
(Token::Whitespace, " ".into()),
(Token::Number, "4".into()),
]
.into_iter()
.peekable(),
}
.parse();
print(0, &ast);
}