summaryrefslogtreecommitdiffstats
path: root/vendor/rowan/examples/math.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rowan/examples/math.rs')
-rw-r--r--vendor/rowan/examples/math.rs152
1 files changed, 152 insertions, 0 deletions
diff --git a/vendor/rowan/examples/math.rs b/vendor/rowan/examples/math.rs
new file mode 100644
index 000000000..930c591b0
--- /dev/null
+++ b/vendor/rowan/examples/math.rs
@@ -0,0 +1,152 @@
+//! 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<SyntaxKind> 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::<u16, SyntaxKind>(raw.0) }
+ }
+ fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
+ kind.into()
+ }
+}
+
+type SyntaxNode = rowan::SyntaxNode<Lang>;
+#[allow(unused)]
+type SyntaxToken = rowan::SyntaxToken<Lang>;
+#[allow(unused)]
+type SyntaxElement = rowan::NodeOrToken<SyntaxNode, SyntaxToken>;
+
+struct Parser<I: Iterator<Item = (SyntaxKind, String)>> {
+ builder: GreenNodeBuilder<'static>,
+ iter: Peekable<I>,
+}
+impl<I: Iterator<Item = (SyntaxKind, String)>> Parser<I> {
+ fn peek(&mut self) -> Option<SyntaxKind> {
+ 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());
+}