From f9a6050034b2ab4358d8a46dd8432de41cebdf0c Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Fri, 18 Jan 2019 14:52:31 +0100 Subject: Move parsing of field pattern lists to the parser (where it belongs) --- crates/ra_hir/src/expr.rs | 16 ++++++--- crates/ra_syntax/src/ast.rs | 49 -------------------------- crates/ra_syntax/src/ast/generated.rs | 35 +++++++++++++++++- crates/ra_syntax/src/grammar.ron | 7 +++- crates/ra_syntax/src/grammar/patterns.rs | 26 +++++++++----- crates/ra_syntax/src/syntax_kinds/generated.rs | 2 ++ 6 files changed, 71 insertions(+), 64 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 1d0beb148..b52f7591d 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -857,11 +857,19 @@ impl ExprCollector { let fields = p .field_pat_list() .expect("every struct should have a field list") - .field_pats() - .into_iter() + .pats() .map(|f| { - let name = Name::new(f.ident); - let pat = self.collect_pat(&*f.pat); + let ast_pat = f.pat().expect("field pat always contains a pattern"); + let pat = self.collect_pat(ast_pat); + let name = f + .name() + .unwrap_or_else(|| { + ast::BindPat::cast(ast_pat.syntax()) + .expect("field pat without label is a bind pat") + .name() + .expect("bind pat has a name") + }) + .as_name(); FieldPat { name, pat } }) .collect(); diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 0ee9ef199..5a5f56057 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -664,55 +664,6 @@ impl LiteralExpr { } } -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct FieldPat { - pub ident: SmolStr, - // FIXME: could we use a regular reference? - pub pat: TreeArc, -} - -impl FieldPatList { - // TODO: try returning an iterator? - // FIXME: shouldnt the parser do this? :o - pub fn field_pats(&self) -> Vec { - let mut child_iter = self.syntax().children(); - let mut pats = Vec::new(); - - while let Some(node) = child_iter.next() { - let kind = node.kind(); - if kind != IDENT && kind != BIND_PAT { - continue; - } - - let ident = if let Some(text) = node.leaf_text() { - text.clone() - } else { - SmolStr::new(node.text().to_string()) - }; - let mut pat = Pat::cast(node).map(AstNode::to_owned); - - // get pat - while let Some(node) = child_iter.next() { - if node.kind() == COMMA { - break; - } - - if let Some(p) = Pat::cast(node) { - pat = Some(p.to_owned()); - } - } - - let field_pat = FieldPat { - ident: ident, - pat: pat.unwrap(), - }; - pats.push(field_pat); - } - - pats - } -} - impl BindPat { pub fn is_mutable(&self) -> bool { self.syntax().children().any(|n| n.kind() == MUT_KW) diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index ead0f1293..23a573d74 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -858,6 +858,35 @@ impl FieldExpr { } } +// FieldPat +#[derive(Debug, PartialEq, Eq, Hash)] +#[repr(transparent)] +pub struct FieldPat { + pub(crate) syntax: SyntaxNode, +} +unsafe impl TransparentNewType for FieldPat { + type Repr = rowan::SyntaxNode; +} + +impl AstNode for FieldPat { + fn cast(syntax: &SyntaxNode) -> Option<&Self> { + match syntax.kind() { + FIELD_PAT => Some(FieldPat::from_repr(syntax.into_repr())), + _ => None, + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } + fn to_owned(&self) -> TreeArc { TreeArc::cast(self.syntax.to_owned()) } +} + + +impl ast::NameOwner for FieldPat {} +impl FieldPat { + pub fn pat(&self) -> Option<&Pat> { + super::child_opt(self) + } +} + // FieldPatList #[derive(Debug, PartialEq, Eq, Hash)] #[repr(transparent)] @@ -880,7 +909,11 @@ impl AstNode for FieldPatList { } -impl FieldPatList {} +impl FieldPatList { + pub fn pats(&self) -> impl Iterator { + super::children(self) + } +} // FloatNumber #[derive(Debug, PartialEq, Eq, Hash)] diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index d58e0dd35..d8c1ae538 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -154,6 +154,7 @@ Grammar( "PATH_PAT", "STRUCT_PAT", "FIELD_PAT_LIST", + "FIELD_PAT", "TUPLE_STRUCT_PAT", "TUPLE_PAT", "SLICE_PAT", @@ -495,7 +496,11 @@ Grammar( "PlaceholderPat": (), "PathPat": ( options: [ "Path" ] ), "StructPat": ( options: ["FieldPatList", "Path"] ), - "FieldPatList": (), + "FieldPatList": ( collections: [["pats", "FieldPat"]] ), + "FieldPat": ( + traits: ["NameOwner"], + options: ["Pat"] + ), "TupleStructPat": ( options: ["Path"], collections: [["args", "Pat"]], diff --git a/crates/ra_syntax/src/grammar/patterns.rs b/crates/ra_syntax/src/grammar/patterns.rs index 7820c4e02..ff9d94f8a 100644 --- a/crates/ra_syntax/src/grammar/patterns.rs +++ b/crates/ra_syntax/src/grammar/patterns.rs @@ -128,15 +128,7 @@ fn field_pat_list(p: &mut Parser) { while !p.at(EOF) && !p.at(R_CURLY) { match p.current() { DOTDOT => p.bump(), - IDENT if p.nth(1) == COLON => { - p.bump(); - p.bump(); - pattern(p); - } - L_CURLY => error_block(p, "expected ident"), - _ => { - bind_pat(p, false); - } + _ => field_pat(p), } if !p.at(R_CURLY) { p.expect(COMMA); @@ -146,6 +138,22 @@ fn field_pat_list(p: &mut Parser) { m.complete(p, FIELD_PAT_LIST); } +fn field_pat(p: &mut Parser) { + let m = p.start(); + match p.current() { + IDENT if p.nth(1) == COLON => { + name(p); + p.bump(); + pattern(p); + } + L_CURLY => error_block(p, "expected ident"), + _ => { + bind_pat(p, false); + } + } + m.complete(p, FIELD_PAT); +} + // test placeholder_pat // fn main() { let _ = (); } fn placeholder_pat(p: &mut Parser) -> CompletedMarker { diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs b/crates/ra_syntax/src/syntax_kinds/generated.rs index 830fac9f4..06faf7557 100644 --- a/crates/ra_syntax/src/syntax_kinds/generated.rs +++ b/crates/ra_syntax/src/syntax_kinds/generated.rs @@ -152,6 +152,7 @@ pub enum SyntaxKind { PATH_PAT, STRUCT_PAT, FIELD_PAT_LIST, + FIELD_PAT, TUPLE_STRUCT_PAT, TUPLE_PAT, SLICE_PAT, @@ -414,6 +415,7 @@ impl SyntaxKind { PATH_PAT => &SyntaxInfo { name: "PATH_PAT" }, STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" }, FIELD_PAT_LIST => &SyntaxInfo { name: "FIELD_PAT_LIST" }, + FIELD_PAT => &SyntaxInfo { name: "FIELD_PAT" }, TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" }, TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" }, SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" }, -- cgit v1.2.3