From d8b2a5efc0e5de3b0d72f29ccc86185f0827c9d3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Aug 2018 17:43:39 +0300 Subject: Generate AST --- src/ast.rs | 94 ----------------------------------------------- src/ast/generated.rs | 54 +++++++++++++++++++++++++++ src/ast/generated.rs.tera | 22 +++++++++++ src/ast/mod.rs | 70 +++++++++++++++++++++++++++++++++++ src/grammar.ron | 11 ++++++ src/lib.rs | 2 +- 6 files changed, 158 insertions(+), 95 deletions(-) delete mode 100644 src/ast.rs create mode 100644 src/ast/generated.rs create mode 100644 src/ast/generated.rs.tera create mode 100644 src/ast/mod.rs (limited to 'src') diff --git a/src/ast.rs b/src/ast.rs deleted file mode 100644 index a595b9324..000000000 --- a/src/ast.rs +++ /dev/null @@ -1,94 +0,0 @@ -use std::sync::Arc; -use { - SyntaxNode, SyntaxRoot, TreeRoot, - SyntaxKind::*, -}; - -#[derive(Debug)] -pub struct File> { - syntax: SyntaxNode, -} - -#[derive(Debug)] -pub struct Function> { - syntax: SyntaxNode, -} - -#[derive(Debug)] -pub struct Name> { - syntax: SyntaxNode, -} - - -impl File> { - pub fn parse(text: &str) -> Self { - File { - syntax: ::parse(text), - } - } -} - -impl File { - pub fn functions<'a>(&'a self) -> impl Iterator> + 'a { - self.syntax - .children() - .filter(|node| node.kind() == FN_ITEM) - .map(|node| Function { syntax: node }) - } -} - -impl Function { - pub fn syntax(&self) -> SyntaxNode { - self.syntax.clone() - } - - pub fn name(&self) -> Option> { - self.syntax - .children() - .filter(|node| node.kind() == NAME) - .map(|node| Name { syntax: node }) - .next() - } - - pub fn has_atom_attr(&self, atom: &str) -> bool { - self.syntax - .children() - .filter(|node| node.kind() == ATTR) - .any(|attr| { - let mut metas = attr.children().filter(|node| node.kind() == META_ITEM); - let meta = match metas.next() { - None => return false, - Some(meta) => { - if metas.next().is_some() { - return false; - } - meta - } - }; - let mut children = meta.children(); - match children.next() { - None => false, - Some(child) => { - if children.next().is_some() { - return false; - } - child.kind() == IDENT && child.text() == atom - } - } - }) - } -} - -impl Name { - pub fn text(&self) -> String { - self.syntax.text() - } -} - - - -impl File { - pub fn syntax(&self) -> SyntaxNode { - self.syntax.clone() - } -} diff --git a/src/ast/generated.rs b/src/ast/generated.rs new file mode 100644 index 000000000..612b04f86 --- /dev/null +++ b/src/ast/generated.rs @@ -0,0 +1,54 @@ +use std::sync::Arc; +use { + SyntaxNode, SyntaxRoot, TreeRoot, AstNode, + SyntaxKind::*, +}; + + +#[derive(Debug)] +pub struct File> { + syntax: SyntaxNode, +} + +impl AstNode for File { + fn cast(syntax: SyntaxNode) -> Option { + match syntax.kind() { + FILE => Some(File { syntax }), + _ => None, + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} + + +#[derive(Debug)] +pub struct FnItem> { + syntax: SyntaxNode, +} + +impl AstNode for FnItem { + fn cast(syntax: SyntaxNode) -> Option { + match syntax.kind() { + FN_ITEM => Some(FnItem { syntax }), + _ => None, + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} + + +#[derive(Debug)] +pub struct Name> { + syntax: SyntaxNode, +} + +impl AstNode for Name { + fn cast(syntax: SyntaxNode) -> Option { + match syntax.kind() { + NAME => Some(Name { syntax }), + _ => None, + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} + diff --git a/src/ast/generated.rs.tera b/src/ast/generated.rs.tera new file mode 100644 index 000000000..f2559383a --- /dev/null +++ b/src/ast/generated.rs.tera @@ -0,0 +1,22 @@ +use std::sync::Arc; +use { + SyntaxNode, SyntaxRoot, TreeRoot, AstNode, + SyntaxKind::*, +}; +{% for node in ast %} +{% set Name = node.kind | camel %} +#[derive(Debug)] +pub struct {{ Name }}> { + syntax: SyntaxNode, +} + +impl AstNode for {{ Name }} { + fn cast(syntax: SyntaxNode) -> Option { + match syntax.kind() { + {{ node.kind }} => Some({{ Name }} { syntax }), + _ => None, + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +{% endfor %} diff --git a/src/ast/mod.rs b/src/ast/mod.rs new file mode 100644 index 000000000..dc7e006c9 --- /dev/null +++ b/src/ast/mod.rs @@ -0,0 +1,70 @@ +mod generated; + +use std::sync::Arc; +use { + SyntaxNode, SyntaxRoot, TreeRoot, + SyntaxKind::*, +}; +pub use self::generated::*; + +pub trait AstNode: Sized { + fn cast(syntax: SyntaxNode) -> Option; + fn syntax(&self) -> &SyntaxNode; +} + +impl File> { + pub fn parse(text: &str) -> Self { + File::cast(::parse(text)).unwrap() + } +} + +impl File { + pub fn functions<'a>(&'a self) -> impl Iterator> + 'a { + self.syntax() + .children() + .filter_map(FnItem::cast) + } +} + +impl FnItem { + pub fn name(&self) -> Option> { + self.syntax() + .children() + .filter_map(Name::cast) + .next() + } + + pub fn has_atom_attr(&self, atom: &str) -> bool { + self.syntax() + .children() + .filter(|node| node.kind() == ATTR) + .any(|attr| { + let mut metas = attr.children().filter(|node| node.kind() == META_ITEM); + let meta = match metas.next() { + None => return false, + Some(meta) => { + if metas.next().is_some() { + return false; + } + meta + } + }; + let mut children = meta.children(); + match children.next() { + None => false, + Some(child) => { + if children.next().is_some() { + return false; + } + child.kind() == IDENT && child.text() == atom + } + } + }) + } +} + +impl Name { + pub fn text(&self) -> String { + self.syntax().text() + } +} diff --git a/src/grammar.ron b/src/grammar.ron index 0443dd798..b6a870d84 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -212,5 +212,16 @@ Grammar( "PARAM", "SELF_PARAM", "ARG_LIST", + ], + ast: [ + ( + kind: "FILE" + ), + ( + kind: "FN_ITEM" + ), + ( + kind: "NAME" + ), ] ) diff --git a/src/lib.rs b/src/lib.rs index 91b0c9c55..d1e690bb2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,7 +41,7 @@ mod yellow; pub mod utils; pub use { - ast::File, + ast::{AstNode, File}, lexer::{tokenize, Token}, syntax_kinds::SyntaxKind, text_unit::{TextRange, TextUnit}, -- cgit v1.2.3