From 50a02eb3593591a02677e1b56f24d7ff0459b9d0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 12 Aug 2020 17:06:49 +0200 Subject: Rename ra_parser -> parser --- crates/parser/src/grammar/items/traits.rs | 153 ++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 crates/parser/src/grammar/items/traits.rs (limited to 'crates/parser/src/grammar/items/traits.rs') diff --git a/crates/parser/src/grammar/items/traits.rs b/crates/parser/src/grammar/items/traits.rs new file mode 100644 index 000000000..751ce65f2 --- /dev/null +++ b/crates/parser/src/grammar/items/traits.rs @@ -0,0 +1,153 @@ +//! FIXME: write short doc here + +use super::*; + +// test trait_item +// trait T: Hash + Clone where U: Copy {} +// trait X: Hash + Clone where U: Copy {} +pub(super) fn trait_def(p: &mut Parser) { + assert!(p.at(T![trait])); + p.bump(T![trait]); + name_r(p, ITEM_RECOVERY_SET); + type_params::opt_type_param_list(p); + // test trait_alias + // trait Z = T; + // trait Z = T where U: Copy; + // trait Z = where Self: T; + if p.eat(T![=]) { + type_params::bounds_without_colon(p); + type_params::opt_where_clause(p); + p.expect(T![;]); + return; + } + if p.at(T![:]) { + type_params::bounds(p); + } + type_params::opt_where_clause(p); + if p.at(T!['{']) { + trait_item_list(p); + } else { + p.error("expected `{`"); + } +} + +// test trait_item_list +// impl F { +// type A: Clone; +// const B: i32; +// fn foo() {} +// fn bar(&self); +// } +pub(crate) fn trait_item_list(p: &mut Parser) { + assert!(p.at(T!['{'])); + let m = p.start(); + p.bump(T!['{']); + while !p.at(EOF) && !p.at(T!['}']) { + if p.at(T!['{']) { + error_block(p, "expected an item"); + continue; + } + item_or_macro(p, true); + } + p.expect(T!['}']); + m.complete(p, ASSOC_ITEM_LIST); +} + +// test impl_def +// impl Foo {} +pub(super) fn impl_def(p: &mut Parser) { + assert!(p.at(T![impl])); + p.bump(T![impl]); + if choose_type_params_over_qpath(p) { + type_params::opt_type_param_list(p); + } + + // FIXME: never type + // impl ! {} + + // test impl_def_neg + // impl !Send for X {} + p.eat(T![!]); + impl_type(p); + if p.eat(T![for]) { + impl_type(p); + } + type_params::opt_where_clause(p); + if p.at(T!['{']) { + impl_item_list(p); + } else { + p.error("expected `{`"); + } +} + +// test impl_item_list +// impl F { +// type A = i32; +// const B: i32 = 92; +// fn foo() {} +// fn bar(&self) {} +// } +pub(crate) fn impl_item_list(p: &mut Parser) { + assert!(p.at(T!['{'])); + let m = p.start(); + p.bump(T!['{']); + // test impl_inner_attributes + // enum F{} + // impl F { + // //! This is a doc comment + // #![doc("This is also a doc comment")] + // } + attributes::inner_attributes(p); + + while !p.at(EOF) && !p.at(T!['}']) { + if p.at(T!['{']) { + error_block(p, "expected an item"); + continue; + } + item_or_macro(p, true); + } + p.expect(T!['}']); + m.complete(p, ASSOC_ITEM_LIST); +} + +// test impl_type_params +// impl Bar {} +fn choose_type_params_over_qpath(p: &Parser) -> bool { + // There's an ambiguity between generic parameters and qualified paths in impls. + // If we see `<` it may start both, so we have to inspect some following tokens. + // The following combinations can only start generics, + // but not qualified paths (with one exception): + // `<` `>` - empty generic parameters + // `<` `#` - generic parameters with attributes + // `<` `const` - const generic parameters + // `<` (LIFETIME|IDENT) `>` - single generic parameter + // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list + // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds + // `<` (LIFETIME|IDENT) `=` - generic parameter with a default + // The only truly ambiguous case is + // `<` IDENT `>` `::` IDENT ... + // we disambiguate it in favor of generics (`impl ::absolute::Path { ... }`) + // because this is what almost always expected in practice, qualified paths in impls + // (`impl ::AssocTy { ... }`) aren't even allowed by type checker at the moment. + if !p.at(T![<]) { + return false; + } + if p.nth(1) == T![#] || p.nth(1) == T![>] || p.nth(1) == CONST_KW { + return true; + } + (p.nth(1) == LIFETIME || p.nth(1) == IDENT) + && (p.nth(2) == T![>] || p.nth(2) == T![,] || p.nth(2) == T![:] || p.nth(2) == T![=]) +} + +// test_err impl_type +// impl Type {} +// impl Trait1 for T {} +// impl impl NotType {} +// impl Trait2 for impl NotType {} +pub(crate) fn impl_type(p: &mut Parser) { + if p.at(T![impl]) { + p.error("expected trait or type"); + return; + } + types::type_(p); +} -- cgit v1.2.3 From 6bc2633c90cedad057c5201d1ab7f67b57247004 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 13 Aug 2020 17:58:35 +0200 Subject: Align parser names with grammar --- crates/parser/src/grammar/items/traits.rs | 38 +++++++------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) (limited to 'crates/parser/src/grammar/items/traits.rs') diff --git a/crates/parser/src/grammar/items/traits.rs b/crates/parser/src/grammar/items/traits.rs index 751ce65f2..8394020da 100644 --- a/crates/parser/src/grammar/items/traits.rs +++ b/crates/parser/src/grammar/items/traits.rs @@ -5,11 +5,11 @@ use super::*; // test trait_item // trait T: Hash + Clone where U: Copy {} // trait X: Hash + Clone where U: Copy {} -pub(super) fn trait_def(p: &mut Parser) { +pub(super) fn trait_(p: &mut Parser) { assert!(p.at(T![trait])); p.bump(T![trait]); name_r(p, ITEM_RECOVERY_SET); - type_params::opt_type_param_list(p); + type_params::opt_generic_param_list(p); // test trait_alias // trait Z = T; // trait Z = T where U: Copy; @@ -25,41 +25,19 @@ pub(super) fn trait_def(p: &mut Parser) { } type_params::opt_where_clause(p); if p.at(T!['{']) { - trait_item_list(p); + assoc_item_list(p); } else { p.error("expected `{`"); } } -// test trait_item_list -// impl F { -// type A: Clone; -// const B: i32; -// fn foo() {} -// fn bar(&self); -// } -pub(crate) fn trait_item_list(p: &mut Parser) { - assert!(p.at(T!['{'])); - let m = p.start(); - p.bump(T!['{']); - while !p.at(EOF) && !p.at(T!['}']) { - if p.at(T!['{']) { - error_block(p, "expected an item"); - continue; - } - item_or_macro(p, true); - } - p.expect(T!['}']); - m.complete(p, ASSOC_ITEM_LIST); -} - // test impl_def // impl Foo {} -pub(super) fn impl_def(p: &mut Parser) { +pub(super) fn impl_(p: &mut Parser) { assert!(p.at(T![impl])); p.bump(T![impl]); if choose_type_params_over_qpath(p) { - type_params::opt_type_param_list(p); + type_params::opt_generic_param_list(p); } // FIXME: never type @@ -74,7 +52,7 @@ pub(super) fn impl_def(p: &mut Parser) { } type_params::opt_where_clause(p); if p.at(T!['{']) { - impl_item_list(p); + assoc_item_list(p); } else { p.error("expected `{`"); } @@ -87,7 +65,7 @@ pub(super) fn impl_def(p: &mut Parser) { // fn foo() {} // fn bar(&self) {} // } -pub(crate) fn impl_item_list(p: &mut Parser) { +pub(crate) fn assoc_item_list(p: &mut Parser) { assert!(p.at(T!['{'])); let m = p.start(); p.bump(T!['{']); @@ -97,7 +75,7 @@ pub(crate) fn impl_item_list(p: &mut Parser) { // //! This is a doc comment // #![doc("This is also a doc comment")] // } - attributes::inner_attributes(p); + attributes::inner_attrs(p); while !p.at(EOF) && !p.at(T!['}']) { if p.at(T!['{']) { -- cgit v1.2.3