From 3d28292157e1b6c9675ef64eddf53786c3e7dc5f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 29 Jul 2020 15:45:23 +0200 Subject: Switch to ungrammar from ast_src The primary advantage of ungrammar is that it (eventually) allows one to describe concrete syntax tree structure -- with alternatives and specific sequence of tokens & nodes. That should be re-usable for: * generate `make` calls * Rust reference * Hypothetical parser's evented API We loose doc comments for the time being unfortunately. I don't think we should add support for doc comments to ungrammar -- they'll make grammar file hard to read. We might supply docs as out-of band info, or maybe just via a reference, but we'll think about that once things are no longer in flux --- Cargo.lock | 7 + crates/ra_hir_def/src/type_ref.rs | 2 +- crates/ra_syntax/src/ast/expr_ext.rs | 2 + crates/ra_syntax/src/ast/generated/nodes.rs | 3020 +++++++-------------------- crates/ra_syntax/src/ast/node_ext.rs | 16 + xtask/Cargo.toml | 9 +- xtask/src/ast_src.rs | 1984 +----------------- xtask/src/codegen/gen_syntax.rs | 224 +- xtask/src/codegen/rust.ungram | 529 +++++ 9 files changed, 1596 insertions(+), 4197 deletions(-) create mode 100644 xtask/src/codegen/rust.ungram diff --git a/Cargo.lock b/Cargo.lock index ff225399e..b7a9516e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1749,6 +1749,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "ungrammar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee12e4891ab3acc2d95d5023022ace22020247bb8a8d1ece875a443f7dab37d" + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -1893,5 +1899,6 @@ dependencies = [ "pico-args", "proc-macro2", "quote", + "ungrammar", "walkdir", ] diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index e90b2a0b9..970fc9af5 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs @@ -1,7 +1,7 @@ //! HIR for references to types. Paths in these are not yet resolved. They can //! be directly created from an ast::TypeRef, without further queries. -use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner}; +use ra_syntax::ast::{self, TypeAscriptionOwner}; use crate::{body::LowerCtx, path::Path}; diff --git a/crates/ra_syntax/src/ast/expr_ext.rs b/crates/ra_syntax/src/ast/expr_ext.rs index db5438d68..69c85c809 100644 --- a/crates/ra_syntax/src/ast/expr_ext.rs +++ b/crates/ra_syntax/src/ast/expr_ext.rs @@ -7,6 +7,8 @@ use crate::{ SyntaxToken, T, }; +impl ast::AttrsOwner for ast::Expr {} + impl ast::Expr { pub fn is_block_like(&self) -> bool { match self { diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index 1fe5f450a..b2d108a7c 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs @@ -5,48 +5,34 @@ use crate::{ SyntaxKind::{self, *}, SyntaxNode, SyntaxToken, T, }; -/// The entire Rust source file. Includes all top-level inner attributes and module items. -/// -/// [Reference](https://doc.rust-lang.org/reference/crates-and-source-files.html) #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SourceFile { pub(crate) syntax: SyntaxNode, } -impl ast::ModuleItemOwner for SourceFile {} impl ast::AttrsOwner for SourceFile {} -impl ast::DocCommentsOwner for SourceFile {} +impl ast::ModuleItemOwner for SourceFile {} impl SourceFile {} -/// Function definition either with body or not. -/// Includes all of its attributes and doc comments. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// pub extern "C" fn foo(#[attr] Patern {p}: Pattern) -> u32 -/// where -/// T: Debug -/// { -/// 42 -/// } -/// ❱ -/// -/// extern "C" { -/// ❰ fn fn_decl(also_variadic_ffi: u32, ...) -> u32; ❱ -/// } -/// ``` -/// -/// - [Reference](https://doc.rust-lang.org/reference/items/functions.html) -/// - [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions) +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Attr { + pub(crate) syntax: SyntaxNode, +} +impl Attr { + pub fn pound_token(&self) -> Option { support::token(&self.syntax, T![#]) } + pub fn excl_token(&self) -> Option { support::token(&self.syntax, T![!]) } + pub fn l_brack_token(&self) -> Option { support::token(&self.syntax, T!['[']) } + pub fn path(&self) -> Option { support::child(&self.syntax) } + pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } + pub fn input(&self) -> Option { support::child(&self.syntax) } + pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FnDef { pub(crate) syntax: SyntaxNode, } -impl ast::VisibilityOwner for FnDef {} +impl ast::AttrsOwner for FnDef {} impl ast::NameOwner for FnDef {} +impl ast::VisibilityOwner for FnDef {} impl ast::TypeParamsOwner for FnDef {} -impl ast::DocCommentsOwner for FnDef {} -impl ast::AttrsOwner for FnDef {} impl FnDef { pub fn abi(&self) -> Option { support::child(&self.syntax) } pub fn const_token(&self) -> Option { support::token(&self.syntax, T![const]) } @@ -59,13 +45,53 @@ impl FnDef { pub fn body(&self) -> Option { support::child(&self.syntax) } pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } } -/// Return type annotation. -/// -/// ``` -/// fn foo(a: u32) ❰ -> Option ❱ { Some(a) } -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/functions.html) +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Visibility { + pub(crate) syntax: SyntaxNode, +} +impl Visibility { + pub fn pub_token(&self) -> Option { support::token(&self.syntax, T![pub]) } + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + pub fn super_token(&self) -> Option { support::token(&self.syntax, T![super]) } + pub fn self_token(&self) -> Option { support::token(&self.syntax, T![self]) } + pub fn crate_token(&self) -> Option { support::token(&self.syntax, T![crate]) } + pub fn in_token(&self) -> Option { support::token(&self.syntax, T![in]) } + pub fn path(&self) -> Option { support::child(&self.syntax) } + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Abi { + pub(crate) syntax: SyntaxNode, +} +impl Abi {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Name { + pub(crate) syntax: SyntaxNode, +} +impl Name { + pub fn ident_token(&self) -> Option { support::token(&self.syntax, T![ident]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TypeParamList { + pub(crate) syntax: SyntaxNode, +} +impl TypeParamList { + pub fn l_angle_token(&self) -> Option { support::token(&self.syntax, T![<]) } + pub fn type_params(&self) -> AstChildren { support::children(&self.syntax) } + pub fn lifetime_params(&self) -> AstChildren { support::children(&self.syntax) } + pub fn const_params(&self) -> AstChildren { support::children(&self.syntax) } + pub fn r_angle_token(&self) -> Option { support::token(&self.syntax, T![>]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ParamList { + pub(crate) syntax: SyntaxNode, +} +impl ParamList { + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + pub fn self_param(&self) -> Option { support::child(&self.syntax) } + pub fn params(&self) -> AstChildren { support::children(&self.syntax) } + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RetType { pub(crate) syntax: SyntaxNode, @@ -74,204 +100,105 @@ impl RetType { pub fn thin_arrow_token(&self) -> Option { support::token(&self.syntax, T![->]) } pub fn type_ref(&self) -> Option { support::child(&self.syntax) } } -/// Struct definition. -/// Includes all of its attributes and doc comments. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// struct Foo where T: Debug { -/// /// Docs -/// #[attr] -/// pub a: u32, -/// b: T, -/// } -/// ❱ -/// -/// ❰ struct Foo; ❱ -/// ❰ struct Foo(#[attr] T) where T: Debug; ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/structs.html) +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct WhereClause { + pub(crate) syntax: SyntaxNode, +} +impl WhereClause { + pub fn where_token(&self) -> Option { support::token(&self.syntax, T![where]) } + pub fn predicates(&self) -> AstChildren { support::children(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct BlockExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for BlockExpr {} +impl ast::ModuleItemOwner for BlockExpr {} +impl BlockExpr { + pub fn label(&self) -> Option