mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 21:28:51 +00:00
Drop high-order combinators
This commit is contained in:
parent
3c612bfa3a
commit
410f948c5f
4 changed files with 136 additions and 137 deletions
|
@ -2,59 +2,55 @@ use super::*;
|
||||||
|
|
||||||
pub(super) fn mod_contents(p: &mut Parser) {
|
pub(super) fn mod_contents(p: &mut Parser) {
|
||||||
attributes::inner_attributes(p);
|
attributes::inner_attributes(p);
|
||||||
repeat(p, |p| {
|
while !p.at(EOF) {
|
||||||
skip_to_first(
|
item(p);
|
||||||
p, item_first, mod_contents_item,
|
|
||||||
"expected item",
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn item_first(p: &Parser) -> bool {
|
|
||||||
match p.current() {
|
|
||||||
STRUCT_KW | FN_KW | EXTERN_KW | MOD_KW | USE_KW | POUND | PUB_KW => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mod_contents_item(p: &mut Parser) {
|
fn item(p: &mut Parser){
|
||||||
if item(p) {
|
|
||||||
if p.current() == SEMI {
|
|
||||||
node(p, ERROR, |p| {
|
|
||||||
p.error()
|
|
||||||
.message("expected item, found `;`\n\
|
|
||||||
consider removing this semicolon")
|
|
||||||
.emit();
|
|
||||||
p.bump();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn item(p: &mut Parser) -> bool {
|
|
||||||
let attrs_start = p.mark();
|
let attrs_start = p.mark();
|
||||||
attributes::outer_attributes(p);
|
attributes::outer_attributes(p);
|
||||||
visibility(p);
|
visibility(p);
|
||||||
// node_if(p, USE_KW, USE_ITEM, use_item)
|
let la = p.raw_lookahead(1);
|
||||||
// || extern crate_fn
|
|
||||||
// || node_if(p, STATIC_KW, STATIC_ITEM, static_item)
|
|
||||||
// || node_if(p, CONST_KW, CONST_ITEM, const_item) or const FN!
|
|
||||||
// || unsafe trait, impl
|
|
||||||
// || node_if(p, FN_KW, FN_ITEM, fn_item)
|
|
||||||
// || node_if(p, TYPE_KW, TYPE_ITEM, type_item)
|
|
||||||
let item_start = p.mark();
|
let item_start = p.mark();
|
||||||
let item_parsed = node_if(p, [EXTERN_KW, CRATE_KW], EXTERN_CRATE_ITEM, extern_crate_item)
|
match p.current() {
|
||||||
|| node_if(p, MOD_KW, MOD_ITEM, mod_item)
|
EXTERN_KW if la == CRATE_KW => extern_crate_item(p),
|
||||||
|| node_if(p, USE_KW, USE_ITEM, use_item)
|
MOD_KW => mod_item(p),
|
||||||
|| node_if(p, STRUCT_KW, STRUCT_ITEM, struct_item)
|
USE_KW => use_item(p),
|
||||||
|| node_if(p, FN_KW, FN_ITEM, fn_item);
|
STRUCT_KW => struct_item(p),
|
||||||
|
FN_KW => fn_item(p),
|
||||||
|
err_token => {
|
||||||
|
p.start(ERROR);
|
||||||
|
let message = if err_token == SEMI {
|
||||||
|
//TODO: if the item is incomplete, this messsage is misleading
|
||||||
|
"expected item, found `;`\n\
|
||||||
|
consider removing this semicolon"
|
||||||
|
} else {
|
||||||
|
"expected item"
|
||||||
|
};
|
||||||
|
p.error()
|
||||||
|
.message(message)
|
||||||
|
.emit();
|
||||||
|
p.bump();
|
||||||
|
p.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
p.forward_parent(attrs_start, item_start);
|
p.forward_parent(attrs_start, item_start);
|
||||||
item_parsed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_item(p: &mut Parser) {
|
fn struct_item(p: &mut Parser) {
|
||||||
|
p.start(STRUCT_ITEM);
|
||||||
|
|
||||||
|
assert!(p.at(STRUCT_KW));
|
||||||
|
p.bump();
|
||||||
|
|
||||||
|
struct_inner(p);
|
||||||
|
p.finish();
|
||||||
|
|
||||||
|
fn struct_inner(p: &mut Parser) {
|
||||||
if !p.expect(IDENT) {
|
if !p.expect(IDENT) {
|
||||||
|
p.finish();
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
generic_parameters(p);
|
generic_parameters(p);
|
||||||
|
@ -92,6 +88,7 @@ fn struct_item(p: &mut Parser) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn named_fields(p: &mut Parser) {
|
fn named_fields(p: &mut Parser) {
|
||||||
p.curly_block(|p| comma_list(p, EOF, |p| {
|
p.curly_block(|p| comma_list(p, EOF, |p| {
|
||||||
|
@ -135,26 +132,42 @@ fn where_clause(_: &mut Parser) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extern_crate_item(p: &mut Parser) {
|
fn extern_crate_item(p: &mut Parser) {
|
||||||
|
p.start(EXTERN_CRATE_ITEM);
|
||||||
|
|
||||||
|
assert!(p.at(EXTERN_KW));
|
||||||
|
p.bump();
|
||||||
|
|
||||||
|
assert!(p.at(CRATE_KW));
|
||||||
|
p.bump();
|
||||||
|
|
||||||
p.expect(IDENT) && alias(p) && p.expect(SEMI);
|
p.expect(IDENT) && alias(p) && p.expect(SEMI);
|
||||||
|
p.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mod_item(p: &mut Parser) {
|
fn mod_item(p: &mut Parser) {
|
||||||
if !p.expect(IDENT) {
|
p.start(MOD_ITEM);
|
||||||
return;
|
|
||||||
}
|
assert!(p.at(MOD_KW));
|
||||||
if p.eat(SEMI) {
|
p.bump();
|
||||||
return;
|
|
||||||
}
|
if p.expect(IDENT) && !p.eat(SEMI) {
|
||||||
p.curly_block(mod_contents);
|
p.curly_block(mod_contents);
|
||||||
}
|
}
|
||||||
|
p.finish()
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool {
|
pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool {
|
||||||
kind == STAR || kind == L_CURLY
|
kind == STAR || kind == L_CURLY
|
||||||
}
|
}
|
||||||
|
|
||||||
fn use_item(p: &mut Parser) {
|
fn use_item(p: &mut Parser) {
|
||||||
|
p.start(USE_ITEM);
|
||||||
|
|
||||||
|
assert!(p.at(USE_KW));
|
||||||
|
p.bump();
|
||||||
use_tree(p);
|
use_tree(p);
|
||||||
p.expect(SEMI);
|
p.expect(SEMI);
|
||||||
|
p.finish();
|
||||||
|
|
||||||
fn use_tree(p: &mut Parser) -> bool{
|
fn use_tree(p: &mut Parser) -> bool{
|
||||||
if node_if(p, STAR, USE_TREE, |_| ()) {
|
if node_if(p, STAR, USE_TREE, |_| ()) {
|
||||||
|
@ -210,8 +223,14 @@ fn use_item(p: &mut Parser) {
|
||||||
|
|
||||||
|
|
||||||
fn fn_item(p: &mut Parser) {
|
fn fn_item(p: &mut Parser) {
|
||||||
|
p.start(FN_ITEM);
|
||||||
|
|
||||||
|
assert!(p.at(FN_KW));
|
||||||
|
p.bump();
|
||||||
|
|
||||||
p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN)
|
p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN)
|
||||||
&& p.curly_block(|_| ());
|
&& p.curly_block(|_| ());
|
||||||
|
p.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,37 +10,39 @@ mod types;
|
||||||
mod paths;
|
mod paths;
|
||||||
|
|
||||||
pub(crate) fn file(p: &mut Parser) {
|
pub(crate) fn file(p: &mut Parser) {
|
||||||
node(p, FILE, |p| {
|
p.start(FILE);
|
||||||
p.eat(SHEBANG);
|
p.eat(SHEBANG);
|
||||||
items::mod_contents(p);
|
items::mod_contents(p);
|
||||||
})
|
p.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visibility(p: &mut Parser) {
|
fn visibility(p: &mut Parser) {
|
||||||
node_if(p, PUB_KW, VISIBILITY, |p| {
|
if p.at(PUB_KW) {
|
||||||
if p.current() != L_PAREN {
|
p.start(VISIBILITY);
|
||||||
return
|
p.bump();
|
||||||
}
|
if p.at(L_PAREN) {
|
||||||
match p.raw_lookahead(1) {
|
match p.raw_lookahead(1) {
|
||||||
CRATE_KW | SELF_KW | SUPER_KW => {
|
CRATE_KW | SELF_KW | SUPER_KW | IN_KW => {
|
||||||
p.bump();
|
|
||||||
p.bump();
|
|
||||||
}
|
|
||||||
IN_KW => {
|
|
||||||
p.bump();
|
|
||||||
p.bump();
|
p.bump();
|
||||||
|
if p.bump() == IN_KW {
|
||||||
paths::use_path(p);
|
paths::use_path(p);
|
||||||
}
|
}
|
||||||
_ => return
|
|
||||||
}
|
|
||||||
p.expect(R_PAREN);
|
p.expect(R_PAREN);
|
||||||
});
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alias(p: &mut Parser) -> bool {
|
fn alias(p: &mut Parser) -> bool {
|
||||||
node_if(p, AS_KW, ALIAS, |p| {
|
if p.at(AS_KW) {
|
||||||
|
p.start(ALIAS);
|
||||||
|
p.bump();
|
||||||
p.expect(IDENT);
|
p.expect(IDENT);
|
||||||
});
|
p.finish();
|
||||||
|
}
|
||||||
true //FIXME: return false if three are errors
|
true //FIXME: return false if three are errors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,40 +94,13 @@ fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, end: SyntaxKind, f: F)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn skip_to_first<C, F>(p: &mut Parser, cond: C, f: F, message: &str) -> bool
|
impl<'p> Parser<'p> {
|
||||||
where
|
fn at(&self, kind: SyntaxKind) -> bool {
|
||||||
C: Fn(&Parser) -> bool,
|
self.current() == kind
|
||||||
F: FnOnce(&mut Parser),
|
|
||||||
{
|
|
||||||
let mut skipped = false;
|
|
||||||
loop {
|
|
||||||
if cond(p) {
|
|
||||||
if skipped {
|
|
||||||
p.finish();
|
|
||||||
}
|
|
||||||
f(p);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if p.current() == EOF {
|
|
||||||
if skipped {
|
|
||||||
p.finish();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if !skipped {
|
|
||||||
p.start(ERROR);
|
|
||||||
p.error()
|
|
||||||
.message(message)
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
p.bump();
|
|
||||||
skipped = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p> Parser<'p> {
|
|
||||||
pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
|
pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
|
||||||
if self.current() == kind {
|
if self.at(kind) {
|
||||||
self.bump();
|
self.bump();
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
FILE@[0; 21)
|
FILE@[0; 21)
|
||||||
ERROR@[0; 10)
|
ERROR@[0; 3)
|
||||||
err: `expected item`
|
err: `expected item`
|
||||||
IDENT@[0; 2)
|
IDENT@[0; 2)
|
||||||
WHITESPACE@[2; 3)
|
WHITESPACE@[2; 3)
|
||||||
|
ERROR@[3; 10)
|
||||||
|
err: `expected item`
|
||||||
IDENT@[3; 8)
|
IDENT@[3; 8)
|
||||||
WHITESPACE@[8; 10)
|
WHITESPACE@[8; 10)
|
||||||
STRUCT_ITEM@[10; 21)
|
STRUCT_ITEM@[10; 21)
|
||||||
|
|
|
@ -11,7 +11,10 @@ FILE@[0; 12)
|
||||||
PATH_SEGMENT@[9; 9)
|
PATH_SEGMENT@[9; 9)
|
||||||
err: `expected identifier`
|
err: `expected identifier`
|
||||||
err: `expected SEMI`
|
err: `expected SEMI`
|
||||||
ERROR@[9; 12)
|
ERROR@[9; 11)
|
||||||
err: `expected item`
|
err: `expected item`
|
||||||
INT_NUMBER@[9; 11)
|
INT_NUMBER@[9; 11)
|
||||||
|
ERROR@[11; 12)
|
||||||
|
err: `expected item, found `;`
|
||||||
|
consider removing this semicolon`
|
||||||
SEMI@[11; 12)
|
SEMI@[11; 12)
|
||||||
|
|
Loading…
Reference in a new issue