Labeled expressions

This commit is contained in:
Aleksey Kladov 2018-08-24 11:45:14 +03:00
parent 719710a132
commit 89e56c364f
6 changed files with 123 additions and 23 deletions

View file

@ -161,11 +161,12 @@ Grammar(
"PATH_EXPR",
"LAMBDA_EXPR",
"IF_EXPR",
"WHILE_EXPR",
"LOOP_EXPR",
"FOR_EXPR",
"WHILE_EXPR",
"CONTINUE_EXPR",
"BREAK_EXPR",
"FOR_EXPR",
"LABEL",
"BLOCK_EXPR",
"RETURN_EXPR",
"MATCH_EXPR",

View file

@ -30,7 +30,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
token_set_union![
LITERAL_FIRST,
token_set![L_PAREN, PIPE, MOVE_KW, IF_KW, WHILE_KW, MATCH_KW, UNSAFE_KW, L_CURLY, RETURN_KW,
IDENT, SELF_KW, SUPER_KW, COLONCOLON, BREAK_KW, CONTINUE_KW ],
IDENT, SELF_KW, SUPER_KW, COLONCOLON, BREAK_KW, CONTINUE_KW, LIFETIME ],
];
pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> {
@ -48,9 +48,24 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMark
PIPE => lambda_expr(p),
MOVE_KW if la == PIPE => lambda_expr(p),
IF_KW => if_expr(p),
WHILE_KW => while_expr(p),
LOOP_KW => loop_expr(p),
FOR_KW => for_expr(p),
LOOP_KW => loop_expr(p, None),
FOR_KW => for_expr(p, None),
WHILE_KW => while_expr(p, None),
LIFETIME if la == COLON => {
let m = p.start();
label(p);
match p.current() {
LOOP_KW => loop_expr(p, Some(m)),
FOR_KW => for_expr(p, Some(m)),
WHILE_KW => while_expr(p, Some(m)),
_ => {
p.error("expected a loop");
return None;
}
}
}
MATCH_KW => match_expr(p),
UNSAFE_KW if la == L_CURLY => block_expr(p),
L_CURLY => block_expr(p),
@ -164,39 +179,53 @@ fn if_expr(p: &mut Parser) -> CompletedMarker {
m.complete(p, IF_EXPR)
}
// test while_expr
// test label
// fn foo() {
// while true {};
// while let Some(x) = it.next() {};
// 'a: loop {}
// 'b: while true {}
// 'c: for x in () {}
// }
fn while_expr(p: &mut Parser) -> CompletedMarker {
assert!(p.at(WHILE_KW));
fn label(p: &mut Parser) {
assert!(p.at(LIFETIME) && p.nth(1) == COLON);
let m = p.start();
p.bump();
cond(p);
block(p);
m.complete(p, WHILE_EXPR)
p.bump();
m.complete(p, LABEL);
}
// test loop_expr
// fn foo() {
// loop {};
// }
fn loop_expr(p: &mut Parser) -> CompletedMarker {
fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(LOOP_KW));
let m = p.start();
let m = m.unwrap_or_else(|| p.start());
p.bump();
block(p);
m.complete(p, LOOP_EXPR)
}
// test while_expr
// fn foo() {
// while true {};
// while let Some(x) = it.next() {};
// }
fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(WHILE_KW));
let m = m.unwrap_or_else(|| p.start());
p.bump();
cond(p);
block(p);
m.complete(p, WHILE_EXPR)
}
// test for_expr
// fn foo() {
// for x in [] {};
// }
fn for_expr(p: &mut Parser) -> CompletedMarker {
fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(FOR_KW));
let m = p.start();
let m = m.unwrap_or_else(|| p.start());
p.bump();
patterns::pattern(p);
p.expect(IN_KW);

View file

@ -32,7 +32,7 @@ mod type_params;
mod types;
use {
parser_api::{CompletedMarker, Parser, TokenSet},
parser_api::{Marker, CompletedMarker, Parser, TokenSet},
SyntaxKind::{self, *},
};

View file

@ -157,11 +157,12 @@ pub enum SyntaxKind {
PATH_EXPR,
LAMBDA_EXPR,
IF_EXPR,
WHILE_EXPR,
LOOP_EXPR,
FOR_EXPR,
WHILE_EXPR,
CONTINUE_EXPR,
BREAK_EXPR,
FOR_EXPR,
LABEL,
BLOCK_EXPR,
RETURN_EXPR,
MATCH_EXPR,
@ -406,11 +407,12 @@ impl SyntaxKind {
PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" },
LAMBDA_EXPR => &SyntaxInfo { name: "LAMBDA_EXPR" },
IF_EXPR => &SyntaxInfo { name: "IF_EXPR" },
WHILE_EXPR => &SyntaxInfo { name: "WHILE_EXPR" },
LOOP_EXPR => &SyntaxInfo { name: "LOOP_EXPR" },
FOR_EXPR => &SyntaxInfo { name: "FOR_EXPR" },
WHILE_EXPR => &SyntaxInfo { name: "WHILE_EXPR" },
CONTINUE_EXPR => &SyntaxInfo { name: "CONTINUE_EXPR" },
BREAK_EXPR => &SyntaxInfo { name: "BREAK_EXPR" },
FOR_EXPR => &SyntaxInfo { name: "FOR_EXPR" },
LABEL => &SyntaxInfo { name: "LABEL" },
BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" },
RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" },
MATCH_EXPR => &SyntaxInfo { name: "MATCH_EXPR" },