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" },

View file

@ -0,0 +1,5 @@
fn foo() {
'a: loop {}
'b: while true {}
'c: for x in () {}
}

View file

@ -0,0 +1,63 @@
FILE@[0; 74)
FN_DEF@[0; 73)
FN_KW@[0; 2)
WHITESPACE@[2; 3)
NAME@[3; 6)
IDENT@[3; 6) "foo"
PARAM_LIST@[6; 8)
L_PAREN@[6; 7)
R_PAREN@[7; 8)
WHITESPACE@[8; 9)
BLOCK_EXPR@[9; 73)
L_CURLY@[9; 10)
WHITESPACE@[10; 15)
EXPR_STMT@[15; 26)
LOOP_EXPR@[15; 26)
LABEL@[15; 18)
LIFETIME@[15; 17) "'a"
COLON@[17; 18)
WHITESPACE@[18; 19)
LOOP_KW@[19; 23)
WHITESPACE@[23; 24)
BLOCK_EXPR@[24; 26)
L_CURLY@[24; 25)
R_CURLY@[25; 26)
WHITESPACE@[26; 31)
EXPR_STMT@[31; 48)
WHILE_EXPR@[31; 48)
LABEL@[31; 34)
LIFETIME@[31; 33) "'b"
COLON@[33; 34)
WHITESPACE@[34; 35)
WHILE_KW@[35; 40)
WHITESPACE@[40; 41)
LITERAL@[41; 45)
TRUE_KW@[41; 45)
WHITESPACE@[45; 46)
BLOCK_EXPR@[46; 48)
L_CURLY@[46; 47)
R_CURLY@[47; 48)
WHITESPACE@[48; 53)
FOR_EXPR@[53; 71)
LABEL@[53; 56)
LIFETIME@[53; 55) "'c"
COLON@[55; 56)
WHITESPACE@[56; 57)
FOR_KW@[57; 60)
WHITESPACE@[60; 61)
BIND_PAT@[61; 62)
NAME@[61; 62)
IDENT@[61; 62) "x"
WHITESPACE@[62; 63)
IN_KW@[63; 65)
WHITESPACE@[65; 66)
TUPLE_EXPR@[66; 68)
L_PAREN@[66; 67)
R_PAREN@[67; 68)
WHITESPACE@[68; 69)
BLOCK_EXPR@[69; 71)
L_CURLY@[69; 70)
R_CURLY@[70; 71)
WHITESPACE@[71; 72)
R_CURLY@[72; 73)
WHITESPACE@[73; 74)