From 7094291573dc819e3115950ec3b2316bd5e9ea33 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 16 Aug 2018 12:51:40 +0300 Subject: tt-attrs --- crates/libsyntax2/src/ast/generated.rs | 52 +++++++++++++++++++++++++++ crates/libsyntax2/src/ast/mod.rs | 53 +++++++++++++-------------- crates/libsyntax2/src/grammar.ron | 20 ++++++----- crates/libsyntax2/src/grammar/attributes.rs | 56 +++-------------------------- crates/libsyntax2/src/grammar/items/mod.rs | 7 ++-- 5 files changed, 97 insertions(+), 91 deletions(-) (limited to 'crates/libsyntax2/src') diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs index 1ec05c950..c575e15df 100644 --- a/crates/libsyntax2/src/ast/generated.rs +++ b/crates/libsyntax2/src/ast/generated.rs @@ -23,6 +23,31 @@ impl AstNode for ArrayType { impl ArrayType {} +// Attr +#[derive(Debug, Clone, Copy)] +pub struct Attr> { + syntax: SyntaxNode, +} + +impl AstNode for Attr { + fn cast(syntax: SyntaxNode) -> Option { + match syntax.kind() { + ATTR => Some(Attr { syntax }), + _ => None, + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} + +impl Attr { + pub fn value(&self) -> Option> { + self.syntax() + .children() + .filter_map(TokenTree::cast) + .next() + } +} + // ConstDef #[derive(Debug, Clone, Copy)] pub struct ConstDef> { @@ -40,6 +65,7 @@ impl AstNode for ConstDef { } impl ast::NameOwner for ConstDef {} +impl ast::AttrsOwner for ConstDef {} impl ConstDef {} // DynTraitType @@ -77,6 +103,7 @@ impl AstNode for EnumDef { } impl ast::NameOwner for EnumDef {} +impl ast::AttrsOwner for EnumDef {} impl EnumDef {} // File @@ -120,6 +147,7 @@ impl AstNode for FnDef { } impl ast::NameOwner for FnDef {} +impl ast::AttrsOwner for FnDef {} impl FnDef {} // FnPointerType @@ -211,6 +239,7 @@ impl AstNode for Module { } impl ast::NameOwner for Module {} +impl ast::AttrsOwner for Module {} impl Module {} // Name @@ -266,6 +295,7 @@ impl AstNode for NamedField { } impl ast::NameOwner for NamedField {} +impl ast::AttrsOwner for NamedField {} impl NamedField {} // NeverType @@ -436,6 +466,7 @@ impl AstNode for StaticDef { } impl ast::NameOwner for StaticDef {} +impl ast::AttrsOwner for StaticDef {} impl StaticDef {} // StructDef @@ -455,6 +486,7 @@ impl AstNode for StructDef { } impl ast::NameOwner for StructDef {} +impl ast::AttrsOwner for StructDef {} impl StructDef { pub fn fields<'a>(&'a self) -> impl Iterator> + 'a { self.syntax() @@ -463,6 +495,24 @@ impl StructDef { } } +// TokenTree +#[derive(Debug, Clone, Copy)] +pub struct TokenTree> { + syntax: SyntaxNode, +} + +impl AstNode for TokenTree { + fn cast(syntax: SyntaxNode) -> Option { + match syntax.kind() { + TOKEN_TREE => Some(TokenTree { syntax }), + _ => None, + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} + +impl TokenTree {} + // TraitDef #[derive(Debug, Clone, Copy)] pub struct TraitDef> { @@ -480,6 +530,7 @@ impl AstNode for TraitDef { } impl ast::NameOwner for TraitDef {} +impl ast::AttrsOwner for TraitDef {} impl TraitDef {} // TupleType @@ -517,6 +568,7 @@ impl AstNode for TypeDef { } impl ast::NameOwner for TypeDef {} +impl ast::AttrsOwner for TypeDef {} impl TypeDef {} // TypeRef diff --git a/crates/libsyntax2/src/ast/mod.rs b/crates/libsyntax2/src/ast/mod.rs index 679e292a2..fe8f91d15 100644 --- a/crates/libsyntax2/src/ast/mod.rs +++ b/crates/libsyntax2/src/ast/mod.rs @@ -2,10 +2,11 @@ mod generated; use std::sync::Arc; +use itertools::Itertools; use smol_str::SmolStr; use { - SyntaxNode, SyntaxRoot, TreeRoot, SyntaxError, + SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot, SyntaxError, SyntaxKind::*, }; pub use self::generated::*; @@ -14,6 +15,9 @@ pub trait AstNode { fn cast(syntax: SyntaxNode) -> Option where Self: Sized; fn syntax(&self) -> &SyntaxNode; + fn syntax_ref<'a>(&'a self) -> SyntaxNodeRef<'a> where R: 'a { + self.syntax().as_ref() + } } pub trait NameOwner: AstNode { @@ -25,6 +29,14 @@ pub trait NameOwner: AstNode { } } +pub trait AttrsOwner: AstNode { + fn attrs<'a>(&'a self) -> Box> + 'a> where R: 'a { + let it = self.syntax().children() + .filter_map(Attr::cast); + Box::new(it) + } +} + impl File> { pub fn parse(text: &str) -> Self { File::cast(::parse(text)).unwrap() @@ -39,31 +51,20 @@ impl File { impl FnDef { 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 - } - } - }) + self.attrs() + .filter_map(|x| x.value()) + .filter_map(|x| as_atom(x)) + .any(|x| x == atom) + } +} + +fn as_atom(tt: TokenTree) -> Option { + let syntax = tt.syntax_ref(); + let (_bra, attr, _ket) = syntax.children().collect_tuple()?; + if attr.kind() == IDENT { + Some(attr.leaf_text().unwrap()) + } else { + None } } diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron index aa28ab922..4e523da9a 100644 --- a/crates/libsyntax2/src/grammar.ron +++ b/crates/libsyntax2/src/grammar.ron @@ -221,24 +221,26 @@ Grammar( ["functions", "FnDef"] ] ), - "FnDef": ( traits: ["NameOwner"] ), + "FnDef": ( traits: ["NameOwner", "AttrsOwner"] ), "StructDef": ( - traits: ["NameOwner"], + traits: ["NameOwner", "AttrsOwner"], collections: [ ["fields", "NamedField"] ] ), - "NamedField": ( traits: ["NameOwner"] ), - "EnumDef": ( traits: ["NameOwner"] ), - "TraitDef": ( traits: ["NameOwner"] ), - "Module": ( traits: ["NameOwner"] ), - "ConstDef": ( traits: ["NameOwner"] ), - "StaticDef": ( traits: ["NameOwner"] ), - "TypeDef": ( traits: ["NameOwner"] ), + "NamedField": ( traits: ["NameOwner", "AttrsOwner"] ), + "EnumDef": ( traits: ["NameOwner", "AttrsOwner"] ), + "TraitDef": ( traits: ["NameOwner", "AttrsOwner"] ), + "Module": ( traits: ["NameOwner", "AttrsOwner"] ), + "ConstDef": ( traits: ["NameOwner", "AttrsOwner"] ), + "StaticDef": ( traits: ["NameOwner", "AttrsOwner"] ), + "TypeDef": ( traits: ["NameOwner", "AttrsOwner"] ), "ImplItem": (), "Name": (), "NameRef": (), + "Attr": ( options: [ ["value", "TokenTree"] ] ), + "TokenTree": (), "ParenType": (), "TupleType": (), diff --git a/crates/libsyntax2/src/grammar/attributes.rs b/crates/libsyntax2/src/grammar/attributes.rs index c411d4d7f..cd30e8a45 100644 --- a/crates/libsyntax2/src/grammar/attributes.rs +++ b/crates/libsyntax2/src/grammar/attributes.rs @@ -22,58 +22,10 @@ fn attribute(p: &mut Parser, inner: bool) { p.bump(); } - if p.expect(L_BRACK) { - meta_item(p); - p.expect(R_BRACK); - } - attr.complete(p, ATTR); -} - -fn meta_item(p: &mut Parser) { - if p.at(IDENT) { - let meta_item = p.start(); - p.bump(); - match p.current() { - EQ => { - p.bump(); - if expressions::literal(p).is_none() { - p.error("expected literal"); - } - } - L_PAREN => meta_item_arg_list(p), - _ => (), - } - meta_item.complete(p, META_ITEM); + if p.at(L_BRACK) { + items::token_tree(p); } else { - p.error("expected attribute value"); - } -} - -fn meta_item_arg_list(p: &mut Parser) { - assert!(p.at(L_PAREN)); - p.bump(); - loop { - match p.current() { - EOF | R_PAREN => break, - IDENT => meta_item(p), - c => if expressions::literal(p).is_none() { - let message = "expected attribute"; - - if items::ITEM_FIRST.contains(c) { - p.error(message); - return; - } - - let err = p.start(); - p.error(message); - p.bump(); - err.complete(p, ERROR); - continue; - }, - } - if !p.at(R_PAREN) { - p.expect(COMMA); - } + p.error("expected `[`"); } - p.expect(R_PAREN); + attr.complete(p, ATTR); } diff --git a/crates/libsyntax2/src/grammar/items/mod.rs b/crates/libsyntax2/src/grammar/items/mod.rs index fc02f0c5c..84cb47748 100644 --- a/crates/libsyntax2/src/grammar/items/mod.rs +++ b/crates/libsyntax2/src/grammar/items/mod.rs @@ -55,9 +55,6 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemF } } -pub(super) const ITEM_FIRST: TokenSet = - token_set![EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, ENUM_KW, FN_KW, PUB_KW, POUND]; - pub(super) enum MaybeItem { None, Item(SyntaxKind), @@ -322,13 +319,14 @@ pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike { flavor } -fn token_tree(p: &mut Parser) { +pub(super) fn token_tree(p: &mut Parser) { let closing_paren_kind = match p.current() { L_CURLY => R_CURLY, L_PAREN => R_PAREN, L_BRACK => R_BRACK, _ => unreachable!(), }; + let m = p.start(); p.bump(); while !p.at(EOF) && !p.at(closing_paren_kind) { match p.current() { @@ -338,4 +336,5 @@ fn token_tree(p: &mut Parser) { } }; p.expect(closing_paren_kind); + m.complete(p, TOKEN_TREE); } -- cgit v1.2.3