mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
nodes for blocks
This commit is contained in:
parent
4d29300396
commit
7edab6ae6b
122 changed files with 1743 additions and 1535 deletions
|
@ -283,25 +283,25 @@ impl<'a> AstNode<'a> for NameRef<'a> {
|
|||
|
||||
impl<'a> NameRef<'a> {}
|
||||
|
||||
// NamedField
|
||||
// NamedFieldDef
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct NamedField<'a> {
|
||||
pub struct NamedFieldDef<'a> {
|
||||
syntax: SyntaxNodeRef<'a>,
|
||||
}
|
||||
|
||||
impl<'a> AstNode<'a> for NamedField<'a> {
|
||||
impl<'a> AstNode<'a> for NamedFieldDef<'a> {
|
||||
fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
|
||||
match syntax.kind() {
|
||||
NAMED_FIELD => Some(NamedField { syntax }),
|
||||
NAMED_FIELD_DEF => Some(NamedFieldDef { syntax }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
|
||||
}
|
||||
|
||||
impl<'a> ast::NameOwner<'a> for NamedField<'a> {}
|
||||
impl<'a> ast::AttrsOwner<'a> for NamedField<'a> {}
|
||||
impl<'a> NamedField<'a> {}
|
||||
impl<'a> ast::NameOwner<'a> for NamedFieldDef<'a> {}
|
||||
impl<'a> ast::AttrsOwner<'a> for NamedFieldDef<'a> {}
|
||||
impl<'a> NamedFieldDef<'a> {}
|
||||
|
||||
// NeverType
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
@ -498,7 +498,7 @@ impl<'a> ast::NameOwner<'a> for StructDef<'a> {}
|
|||
impl<'a> ast::TypeParamsOwner<'a> for StructDef<'a> {}
|
||||
impl<'a> ast::AttrsOwner<'a> for StructDef<'a> {}
|
||||
impl<'a> StructDef<'a> {
|
||||
pub fn fields(self) -> impl Iterator<Item = NamedField<'a>> + 'a {
|
||||
pub fn fields(self) -> impl Iterator<Item = NamedFieldDef<'a>> + 'a {
|
||||
super::children(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,6 +149,7 @@ Grammar(
|
|||
"PLACEHOLDER_PAT",
|
||||
"PATH_PAT",
|
||||
"STRUCT_PAT",
|
||||
"FIELD_PAT_LIST",
|
||||
"TUPLE_STRUCT_PAT",
|
||||
"TUPLE_PAT",
|
||||
"SLICE_PAT",
|
||||
|
@ -170,10 +171,12 @@ Grammar(
|
|||
"BLOCK_EXPR",
|
||||
"RETURN_EXPR",
|
||||
"MATCH_EXPR",
|
||||
"MATCH_ARM_LIST",
|
||||
"MATCH_ARM",
|
||||
"MATCH_GUARD",
|
||||
"STRUCT_LIT",
|
||||
"STRUCT_LIT_FIELD",
|
||||
"NAMED_FIELD_LIST",
|
||||
"NAMED_FIELD",
|
||||
|
||||
// postfix
|
||||
"CALL_EXPR",
|
||||
|
@ -190,14 +193,20 @@ Grammar(
|
|||
"RANGE_EXPR", // just weird
|
||||
"BIN_EXPR",
|
||||
|
||||
|
||||
"EXTERN_BLOCK_EXPR",
|
||||
"BLOCK",
|
||||
"EXTERN_BLOCK",
|
||||
"EXTERN_ITEM_LIST",
|
||||
"ENUM_VARIANT",
|
||||
"NAMED_FIELD",
|
||||
"NAMED_FIELD_DEF_LIST",
|
||||
"NAMED_FIELD_DEF",
|
||||
"POS_FIELD_LIST",
|
||||
"POS_FIELD",
|
||||
"ENUM_VARIANT_LIST",
|
||||
"ITEM_LIST",
|
||||
"ATTR",
|
||||
"META_ITEM", // not an item actually
|
||||
"USE_TREE",
|
||||
"USE_TREE_LIST",
|
||||
"PATH",
|
||||
"PATH_SEGMENT",
|
||||
"LITERAL",
|
||||
|
@ -244,10 +253,10 @@ Grammar(
|
|||
"AttrsOwner",
|
||||
],
|
||||
collections: [
|
||||
["fields", "NamedField"]
|
||||
["fields", "NamedFieldDef"]
|
||||
]
|
||||
),
|
||||
"NamedField": ( traits: ["NameOwner", "AttrsOwner"] ),
|
||||
"NamedFieldDef": ( traits: ["NameOwner", "AttrsOwner"] ),
|
||||
"EnumDef": ( traits: [
|
||||
"NameOwner",
|
||||
"TypeParamsOwner",
|
||||
|
|
|
@ -148,7 +148,11 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
|
|||
p.eat(MOVE_KW);
|
||||
params::param_list_opt_types(p);
|
||||
if opt_fn_ret_type(p) {
|
||||
block(p);
|
||||
if p.at(L_CURLY) {
|
||||
block(p);
|
||||
} else {
|
||||
p.error("expected a block");
|
||||
}
|
||||
} else {
|
||||
expr(p);
|
||||
}
|
||||
|
@ -254,6 +258,17 @@ fn match_expr(p: &mut Parser) -> CompletedMarker {
|
|||
let m = p.start();
|
||||
p.bump();
|
||||
expr_no_struct(p);
|
||||
if p.at(L_CURLY) {
|
||||
match_arm_list(p);
|
||||
} else {
|
||||
p.error("expected `{`")
|
||||
}
|
||||
m.complete(p, MATCH_EXPR)
|
||||
}
|
||||
|
||||
fn match_arm_list(p: &mut Parser) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.eat(L_CURLY);
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
// test match_arms_commas
|
||||
|
@ -271,7 +286,7 @@ fn match_expr(p: &mut Parser) -> CompletedMarker {
|
|||
}
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, MATCH_EXPR)
|
||||
m.complete(p, MATCH_ARM_LIST);
|
||||
}
|
||||
|
||||
// test match_arm
|
||||
|
@ -307,62 +322,10 @@ pub(super) fn block_expr(p: &mut Parser) -> CompletedMarker {
|
|||
assert!(p.at(L_CURLY) || p.at(UNSAFE_KW) && p.nth(1) == L_CURLY);
|
||||
let m = p.start();
|
||||
p.eat(UNSAFE_KW);
|
||||
p.bump();
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
match p.current() {
|
||||
LET_KW => let_stmt(p),
|
||||
_ => {
|
||||
// test block_items
|
||||
// fn a() { fn b() {} }
|
||||
let m = p.start();
|
||||
match items::maybe_item(p, items::ItemFlavor::Mod) {
|
||||
items::MaybeItem::Item(kind) => {
|
||||
m.complete(p, kind);
|
||||
}
|
||||
items::MaybeItem::Modifiers => {
|
||||
m.abandon(p);
|
||||
p.error("expected an item");
|
||||
}
|
||||
// test pub_expr
|
||||
// fn foo() { pub 92; } //FIXME
|
||||
items::MaybeItem::None => {
|
||||
let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
|
||||
if p.eat(SEMI) || (is_blocklike && !p.at(R_CURLY)) {
|
||||
m.complete(p, EXPR_STMT);
|
||||
} else {
|
||||
m.abandon(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
block(p);
|
||||
m.complete(p, BLOCK_EXPR)
|
||||
}
|
||||
|
||||
// test let_stmt;
|
||||
// fn foo() {
|
||||
// let a;
|
||||
// let b: i32;
|
||||
// let c = 92;
|
||||
// let d: i32 = 92;
|
||||
// }
|
||||
fn let_stmt(p: &mut Parser) {
|
||||
assert!(p.at(LET_KW));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
patterns::pattern(p);
|
||||
if p.at(COLON) {
|
||||
types::ascription(p);
|
||||
}
|
||||
if p.eat(EQ) {
|
||||
expressions::expr(p);
|
||||
}
|
||||
p.expect(SEMI);
|
||||
m.complete(p, LET_STMT);
|
||||
}
|
||||
|
||||
// test return_expr
|
||||
// fn foo() {
|
||||
// return;
|
||||
|
|
|
@ -26,11 +26,62 @@ fn expr_no_struct(p: &mut Parser) {
|
|||
// fn c() { 1; 2; }
|
||||
// fn d() { 1; 2 }
|
||||
pub(super) fn block(p: &mut Parser) {
|
||||
if !p.at(L_CURLY) {
|
||||
p.error("expected block");
|
||||
return;
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
match p.current() {
|
||||
LET_KW => let_stmt(p),
|
||||
_ => {
|
||||
// test block_items
|
||||
// fn a() { fn b() {} }
|
||||
let m = p.start();
|
||||
match items::maybe_item(p, items::ItemFlavor::Mod) {
|
||||
items::MaybeItem::Item(kind) => {
|
||||
m.complete(p, kind);
|
||||
}
|
||||
items::MaybeItem::Modifiers => {
|
||||
m.abandon(p);
|
||||
p.error("expected an item");
|
||||
}
|
||||
// test pub_expr
|
||||
// fn foo() { pub 92; } //FIXME
|
||||
items::MaybeItem::None => {
|
||||
let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
|
||||
if p.eat(SEMI) || (is_blocklike && !p.at(R_CURLY)) {
|
||||
m.complete(p, EXPR_STMT);
|
||||
} else {
|
||||
m.abandon(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, BLOCK);
|
||||
|
||||
// test let_stmt;
|
||||
// fn foo() {
|
||||
// let a;
|
||||
// let b: i32;
|
||||
// let c = 92;
|
||||
// let d: i32 = 92;
|
||||
// }
|
||||
fn let_stmt(p: &mut Parser) {
|
||||
assert!(p.at(LET_KW));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
patterns::pattern(p);
|
||||
if p.at(COLON) {
|
||||
types::ascription(p);
|
||||
}
|
||||
if p.eat(EQ) {
|
||||
expressions::expr(p);
|
||||
}
|
||||
p.expect(SEMI);
|
||||
m.complete(p, LET_STMT);
|
||||
}
|
||||
atom::block_expr(p);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -339,7 +390,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
|
|||
paths::expr_path(p);
|
||||
match p.current() {
|
||||
L_CURLY if !r.forbid_structs => {
|
||||
struct_lit(p);
|
||||
named_field_list(p);
|
||||
m.complete(p, STRUCT_LIT)
|
||||
}
|
||||
EXCL => {
|
||||
|
@ -356,8 +407,9 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
|
|||
// S { x, y: 32, };
|
||||
// S { x, y: 32, ..Default::default() };
|
||||
// }
|
||||
fn struct_lit(p: &mut Parser) {
|
||||
fn named_field_list(p: &mut Parser) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
match p.current() {
|
||||
|
@ -367,7 +419,7 @@ fn struct_lit(p: &mut Parser) {
|
|||
if p.eat(COLON) {
|
||||
expr(p);
|
||||
}
|
||||
m.complete(p, STRUCT_LIT_FIELD);
|
||||
m.complete(p, NAMED_FIELD);
|
||||
}
|
||||
DOTDOT => {
|
||||
p.bump();
|
||||
|
@ -380,4 +432,5 @@ fn struct_lit(p: &mut Parser) {
|
|||
}
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, NAMED_FIELD_LIST);
|
||||
}
|
||||
|
|
|
@ -194,8 +194,8 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
|
|||
// extern {}
|
||||
EXTERN_KW if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) => {
|
||||
abi(p);
|
||||
extern_block(p);
|
||||
EXTERN_BLOCK_EXPR
|
||||
extern_item_list(p);
|
||||
EXTERN_BLOCK
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
@ -212,10 +212,12 @@ fn extern_crate_item(p: &mut Parser) {
|
|||
p.expect(SEMI);
|
||||
}
|
||||
|
||||
fn extern_block(p: &mut Parser) {
|
||||
fn extern_item_list(p: &mut Parser) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, EXTERN_ITEM_LIST);
|
||||
}
|
||||
|
||||
fn function(p: &mut Parser, flavor: ItemFlavor) {
|
||||
|
@ -284,14 +286,22 @@ fn mod_item(p: &mut Parser) {
|
|||
p.bump();
|
||||
|
||||
name(p);
|
||||
if !p.eat(SEMI) {
|
||||
if p.expect(L_CURLY) {
|
||||
mod_contents(p, true);
|
||||
p.expect(R_CURLY);
|
||||
}
|
||||
if p.at(L_CURLY) {
|
||||
mod_item_list(p);
|
||||
} else if !p.eat(SEMI) {
|
||||
p.error("expected `;` or `{`");
|
||||
}
|
||||
}
|
||||
|
||||
fn mod_item_list(p: &mut Parser) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
mod_contents(p, true);
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, ITEM_LIST);
|
||||
}
|
||||
|
||||
fn macro_call(p: &mut Parser) -> BlockLike {
|
||||
assert!(paths::is_path_start(p));
|
||||
paths::use_path(p);
|
||||
|
|
|
@ -14,7 +14,7 @@ pub(super) fn struct_def(p: &mut Parser) {
|
|||
p.bump();
|
||||
return;
|
||||
}
|
||||
L_CURLY => named_fields(p),
|
||||
L_CURLY => named_field_def_list(p),
|
||||
_ => {
|
||||
//TODO: special case `(` error message
|
||||
p.error("expected `;` or `{`");
|
||||
|
@ -26,9 +26,9 @@ pub(super) fn struct_def(p: &mut Parser) {
|
|||
p.bump();
|
||||
return;
|
||||
}
|
||||
L_CURLY => named_fields(p),
|
||||
L_CURLY => named_field_def_list(p),
|
||||
L_PAREN => {
|
||||
pos_fields(p);
|
||||
pos_field_list(p);
|
||||
p.expect(SEMI);
|
||||
}
|
||||
_ => {
|
||||
|
@ -44,46 +44,58 @@ pub(super) fn enum_def(p: &mut Parser) {
|
|||
name(p);
|
||||
type_params::opt_type_param_list(p);
|
||||
type_params::opt_where_clause(p);
|
||||
if p.expect(L_CURLY) {
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
let var = p.start();
|
||||
attributes::outer_attributes(p);
|
||||
if p.at(IDENT) {
|
||||
name(p);
|
||||
match p.current() {
|
||||
L_CURLY => named_fields(p),
|
||||
L_PAREN => pos_fields(p),
|
||||
EQ => {
|
||||
p.bump();
|
||||
expressions::expr(p);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
var.complete(p, ENUM_VARIANT);
|
||||
} else {
|
||||
var.abandon(p);
|
||||
p.err_and_bump("expected enum variant");
|
||||
}
|
||||
if !p.at(R_CURLY) {
|
||||
p.expect(COMMA);
|
||||
}
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
if p.at(L_CURLY) {
|
||||
enum_variant_list(p);
|
||||
} else {
|
||||
p.error("expected `{`")
|
||||
}
|
||||
}
|
||||
|
||||
fn named_fields(p: &mut Parser) {
|
||||
fn enum_variant_list(p: &mut Parser) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
while !p.at(R_CURLY) && !p.at(EOF) {
|
||||
named_field(p);
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
let var = p.start();
|
||||
attributes::outer_attributes(p);
|
||||
if p.at(IDENT) {
|
||||
name(p);
|
||||
match p.current() {
|
||||
L_CURLY => named_field_def_list(p),
|
||||
L_PAREN => pos_field_list(p),
|
||||
EQ => {
|
||||
p.bump();
|
||||
expressions::expr(p);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
var.complete(p, ENUM_VARIANT);
|
||||
} else {
|
||||
var.abandon(p);
|
||||
p.err_and_bump("expected enum variant");
|
||||
}
|
||||
if !p.at(R_CURLY) {
|
||||
p.expect(COMMA);
|
||||
}
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, ENUM_VARIANT_LIST);
|
||||
}
|
||||
|
||||
fn named_field(p: &mut Parser) {
|
||||
fn named_field_def_list(p: &mut Parser) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
while !p.at(R_CURLY) && !p.at(EOF) {
|
||||
named_field_def(p);
|
||||
if !p.at(R_CURLY) {
|
||||
p.expect(COMMA);
|
||||
}
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, NAMED_FIELD_DEF_LIST);
|
||||
|
||||
fn named_field_def(p: &mut Parser) {
|
||||
let m = p.start();
|
||||
// test field_attrs
|
||||
// struct S {
|
||||
|
@ -96,7 +108,7 @@ fn named_fields(p: &mut Parser) {
|
|||
name(p);
|
||||
p.expect(COLON);
|
||||
types::type_(p);
|
||||
m.complete(p, NAMED_FIELD);
|
||||
m.complete(p, NAMED_FIELD_DEF);
|
||||
} else {
|
||||
m.abandon(p);
|
||||
p.err_and_bump("expected field declaration");
|
||||
|
@ -104,7 +116,9 @@ fn named_fields(p: &mut Parser) {
|
|||
}
|
||||
}
|
||||
|
||||
fn pos_fields(p: &mut Parser) {
|
||||
fn pos_field_list(p: &mut Parser) {
|
||||
assert!(p.at(L_PAREN));
|
||||
let m = p.start();
|
||||
if !p.expect(L_PAREN) {
|
||||
return;
|
||||
}
|
||||
|
@ -119,4 +133,5 @@ fn pos_fields(p: &mut Parser) {
|
|||
}
|
||||
}
|
||||
p.expect(R_PAREN);
|
||||
m.complete(p, POS_FIELD_LIST);
|
||||
}
|
||||
|
|
|
@ -11,18 +11,29 @@ pub(super) fn trait_def(p: &mut Parser) {
|
|||
type_params::bounds(p);
|
||||
}
|
||||
type_params::opt_where_clause(p);
|
||||
p.expect(L_CURLY);
|
||||
// test trait_item_items
|
||||
// impl F {
|
||||
// type A: Clone;
|
||||
// const B: i32;
|
||||
// fn foo() {}
|
||||
// fn bar(&self);
|
||||
// }
|
||||
if p.at(L_CURLY) {
|
||||
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);
|
||||
// }
|
||||
fn trait_item_list(p: &mut Parser) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
item_or_macro(p, true, ItemFlavor::Trait);
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, ITEM_LIST);
|
||||
}
|
||||
|
||||
// test impl_item
|
||||
|
@ -45,19 +56,30 @@ pub(super) fn impl_item(p: &mut Parser) {
|
|||
types::type_(p);
|
||||
}
|
||||
type_params::opt_where_clause(p);
|
||||
p.expect(L_CURLY);
|
||||
if p.at(L_CURLY) {
|
||||
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) {}
|
||||
// }
|
||||
fn impl_item_list(p: &mut Parser) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
|
||||
// test impl_item_items
|
||||
// impl F {
|
||||
// type A = i32;
|
||||
// const B: i32 = 92;
|
||||
// fn foo() {}
|
||||
// fn bar(&self) {}
|
||||
// }
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
item_or_macro(p, true, ItemFlavor::Mod);
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, ITEM_LIST);
|
||||
}
|
||||
|
||||
fn choose_type_params_over_qpath(p: &Parser) -> bool {
|
||||
|
|
|
@ -20,7 +20,7 @@ fn use_tree(p: &mut Parser) {
|
|||
if p.at(COLONCOLON) {
|
||||
p.bump();
|
||||
}
|
||||
nested_trees(p);
|
||||
use_tree_list(p);
|
||||
}
|
||||
_ if paths::is_path_start(p) => {
|
||||
paths::use_path(p);
|
||||
|
@ -34,7 +34,7 @@ fn use_tree(p: &mut Parser) {
|
|||
STAR => {
|
||||
p.bump();
|
||||
}
|
||||
L_CURLY => nested_trees(p),
|
||||
L_CURLY => use_tree_list(p),
|
||||
_ => {
|
||||
// is this unreachable?
|
||||
p.error("expected `{` or `*`");
|
||||
|
@ -53,8 +53,9 @@ fn use_tree(p: &mut Parser) {
|
|||
m.complete(p, USE_TREE);
|
||||
}
|
||||
|
||||
fn nested_trees(p: &mut Parser) {
|
||||
fn use_tree_list(p: &mut Parser) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
use_tree(p);
|
||||
|
@ -63,4 +64,5 @@ fn nested_trees(p: &mut Parser) {
|
|||
}
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, USE_TREE_LIST);
|
||||
}
|
||||
|
|
|
@ -144,18 +144,21 @@ fn name_ref(p: &mut Parser) {
|
|||
}
|
||||
|
||||
fn error_block(p: &mut Parser, message: &str) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let err = p.start();
|
||||
p.error(message);
|
||||
p.bump();
|
||||
let mut level: u32 = 1;
|
||||
while level > 0 && !p.at(EOF) {
|
||||
match p.current() {
|
||||
L_CURLY => level += 1,
|
||||
R_CURLY => level -= 1,
|
||||
_ => (),
|
||||
go(p, Some(message));
|
||||
fn go(p: &mut Parser, message: Option<&str>) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
if let Some(message) = message {
|
||||
p.error(message);
|
||||
}
|
||||
p.bump();
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
match p.current() {
|
||||
L_CURLY => go(p, None),
|
||||
_ => p.bump(),
|
||||
}
|
||||
}
|
||||
p.eat(R_CURLY);
|
||||
m.complete(p, ERROR);
|
||||
}
|
||||
err.complete(p, ERROR);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ fn path_pat(p: &mut Parser) -> CompletedMarker {
|
|||
TUPLE_STRUCT_PAT
|
||||
}
|
||||
L_CURLY => {
|
||||
struct_pat_fields(p);
|
||||
field_pat_list(p);
|
||||
STRUCT_PAT
|
||||
}
|
||||
_ => PATH_PAT
|
||||
|
@ -99,15 +99,16 @@ fn tuple_pat_fields(p: &mut Parser) {
|
|||
p.expect(R_PAREN);
|
||||
}
|
||||
|
||||
// test struct_pat_fields
|
||||
// test field_pat_list
|
||||
// fn foo() {
|
||||
// let S {} = ();
|
||||
// let S { f, ref mut g } = ();
|
||||
// let S { h: _, ..} = ();
|
||||
// let S { h: _, } = ();
|
||||
// }
|
||||
fn struct_pat_fields(p: &mut Parser) {
|
||||
fn field_pat_list(p: &mut Parser) {
|
||||
assert!(p.at(L_CURLY));
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
match p.current() {
|
||||
|
@ -126,6 +127,7 @@ fn struct_pat_fields(p: &mut Parser) {
|
|||
}
|
||||
}
|
||||
p.expect(R_CURLY);
|
||||
m.complete(p, FIELD_PAT_LIST);
|
||||
}
|
||||
|
||||
// test placeholder_pat
|
||||
|
|
|
@ -53,5 +53,31 @@ pub use {
|
|||
|
||||
pub fn parse(text: &str) -> SyntaxNode {
|
||||
let tokens = tokenize(&text);
|
||||
parser_impl::parse::<yellow::GreenBuilder>(text, &tokens)
|
||||
let res = parser_impl::parse::<yellow::GreenBuilder>(text, &tokens);
|
||||
validate_block_structure(res.borrowed());
|
||||
res
|
||||
}
|
||||
|
||||
fn validate_block_structure(root: SyntaxNodeRef) {
|
||||
let mut stack = Vec::new();
|
||||
for node in algo::walk::preorder(root) {
|
||||
match node.kind() {
|
||||
SyntaxKind::L_CURLY => {
|
||||
stack.push(node)
|
||||
}
|
||||
SyntaxKind::R_CURLY => {
|
||||
if let Some(pair) = stack.pop() {
|
||||
assert_eq!(node.parent(), pair.parent());
|
||||
assert!(
|
||||
node.next_sibling().is_none() && pair.prev_sibling().is_none(),
|
||||
"floating curlys at {:?}\nfile:\n{}\nerror:\n{}\n",
|
||||
node,
|
||||
root.text(),
|
||||
node.text(),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ pub enum SyntaxKind {
|
|||
PLACEHOLDER_PAT,
|
||||
PATH_PAT,
|
||||
STRUCT_PAT,
|
||||
FIELD_PAT_LIST,
|
||||
TUPLE_STRUCT_PAT,
|
||||
TUPLE_PAT,
|
||||
SLICE_PAT,
|
||||
|
@ -166,10 +167,12 @@ pub enum SyntaxKind {
|
|||
BLOCK_EXPR,
|
||||
RETURN_EXPR,
|
||||
MATCH_EXPR,
|
||||
MATCH_ARM_LIST,
|
||||
MATCH_ARM,
|
||||
MATCH_GUARD,
|
||||
STRUCT_LIT,
|
||||
STRUCT_LIT_FIELD,
|
||||
NAMED_FIELD_LIST,
|
||||
NAMED_FIELD,
|
||||
CALL_EXPR,
|
||||
INDEX_EXPR,
|
||||
METHOD_CALL_EXPR,
|
||||
|
@ -180,13 +183,20 @@ pub enum SyntaxKind {
|
|||
PREFIX_EXPR,
|
||||
RANGE_EXPR,
|
||||
BIN_EXPR,
|
||||
EXTERN_BLOCK_EXPR,
|
||||
BLOCK,
|
||||
EXTERN_BLOCK,
|
||||
EXTERN_ITEM_LIST,
|
||||
ENUM_VARIANT,
|
||||
NAMED_FIELD,
|
||||
NAMED_FIELD_DEF_LIST,
|
||||
NAMED_FIELD_DEF,
|
||||
POS_FIELD_LIST,
|
||||
POS_FIELD,
|
||||
ENUM_VARIANT_LIST,
|
||||
ITEM_LIST,
|
||||
ATTR,
|
||||
META_ITEM,
|
||||
USE_TREE,
|
||||
USE_TREE_LIST,
|
||||
PATH,
|
||||
PATH_SEGMENT,
|
||||
LITERAL,
|
||||
|
@ -397,6 +407,7 @@ impl SyntaxKind {
|
|||
PLACEHOLDER_PAT => &SyntaxInfo { name: "PLACEHOLDER_PAT" },
|
||||
PATH_PAT => &SyntaxInfo { name: "PATH_PAT" },
|
||||
STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" },
|
||||
FIELD_PAT_LIST => &SyntaxInfo { name: "FIELD_PAT_LIST" },
|
||||
TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" },
|
||||
TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" },
|
||||
SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" },
|
||||
|
@ -416,10 +427,12 @@ impl SyntaxKind {
|
|||
BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" },
|
||||
RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" },
|
||||
MATCH_EXPR => &SyntaxInfo { name: "MATCH_EXPR" },
|
||||
MATCH_ARM_LIST => &SyntaxInfo { name: "MATCH_ARM_LIST" },
|
||||
MATCH_ARM => &SyntaxInfo { name: "MATCH_ARM" },
|
||||
MATCH_GUARD => &SyntaxInfo { name: "MATCH_GUARD" },
|
||||
STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" },
|
||||
STRUCT_LIT_FIELD => &SyntaxInfo { name: "STRUCT_LIT_FIELD" },
|
||||
NAMED_FIELD_LIST => &SyntaxInfo { name: "NAMED_FIELD_LIST" },
|
||||
NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
|
||||
CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" },
|
||||
INDEX_EXPR => &SyntaxInfo { name: "INDEX_EXPR" },
|
||||
METHOD_CALL_EXPR => &SyntaxInfo { name: "METHOD_CALL_EXPR" },
|
||||
|
@ -430,13 +443,20 @@ impl SyntaxKind {
|
|||
PREFIX_EXPR => &SyntaxInfo { name: "PREFIX_EXPR" },
|
||||
RANGE_EXPR => &SyntaxInfo { name: "RANGE_EXPR" },
|
||||
BIN_EXPR => &SyntaxInfo { name: "BIN_EXPR" },
|
||||
EXTERN_BLOCK_EXPR => &SyntaxInfo { name: "EXTERN_BLOCK_EXPR" },
|
||||
BLOCK => &SyntaxInfo { name: "BLOCK" },
|
||||
EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" },
|
||||
EXTERN_ITEM_LIST => &SyntaxInfo { name: "EXTERN_ITEM_LIST" },
|
||||
ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" },
|
||||
NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
|
||||
NAMED_FIELD_DEF_LIST => &SyntaxInfo { name: "NAMED_FIELD_DEF_LIST" },
|
||||
NAMED_FIELD_DEF => &SyntaxInfo { name: "NAMED_FIELD_DEF" },
|
||||
POS_FIELD_LIST => &SyntaxInfo { name: "POS_FIELD_LIST" },
|
||||
POS_FIELD => &SyntaxInfo { name: "POS_FIELD" },
|
||||
ENUM_VARIANT_LIST => &SyntaxInfo { name: "ENUM_VARIANT_LIST" },
|
||||
ITEM_LIST => &SyntaxInfo { name: "ITEM_LIST" },
|
||||
ATTR => &SyntaxInfo { name: "ATTR" },
|
||||
META_ITEM => &SyntaxInfo { name: "META_ITEM" },
|
||||
USE_TREE => &SyntaxInfo { name: "USE_TREE" },
|
||||
USE_TREE_LIST => &SyntaxInfo { name: "USE_TREE_LIST" },
|
||||
PATH => &SyntaxInfo { name: "PATH" },
|
||||
PATH_SEGMENT => &SyntaxInfo { name: "PATH_SEGMENT" },
|
||||
LITERAL => &SyntaxInfo { name: "LITERAL" },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue