nodes for blocks

This commit is contained in:
Aleksey Kladov
2018-08-24 19:27:30 +03:00
parent 4d29300396
commit 7edab6ae6b
122 changed files with 1743 additions and 1535 deletions

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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