return expr
This commit is contained in:
@@ -70,6 +70,7 @@ Grammar(
|
|||||||
"ref",
|
"ref",
|
||||||
"let",
|
"let",
|
||||||
"move",
|
"move",
|
||||||
|
"return",
|
||||||
],
|
],
|
||||||
contextual_keywords: [
|
contextual_keywords: [
|
||||||
"auto",
|
"auto",
|
||||||
@@ -138,6 +139,8 @@ Grammar(
|
|||||||
"STRUCT_LIT",
|
"STRUCT_LIT",
|
||||||
"STRUCT_LIT_FIELD",
|
"STRUCT_LIT_FIELD",
|
||||||
"IF_EXPR",
|
"IF_EXPR",
|
||||||
|
"BLOCK_EXPR",
|
||||||
|
"RETURN_EXPR",
|
||||||
|
|
||||||
"EXTERN_BLOCK_EXPR",
|
"EXTERN_BLOCK_EXPR",
|
||||||
"ENUM_VARIANT",
|
"ENUM_VARIANT",
|
||||||
@@ -155,7 +158,6 @@ Grammar(
|
|||||||
"ABI",
|
"ABI",
|
||||||
"NAME",
|
"NAME",
|
||||||
"NAME_REF",
|
"NAME_REF",
|
||||||
"BLOCK_EXPR",
|
|
||||||
|
|
||||||
"LET_STMT",
|
"LET_STMT",
|
||||||
"EXPR_STMT",
|
"EXPR_STMT",
|
||||||
|
|||||||
@@ -13,18 +13,20 @@ use super::*;
|
|||||||
// let _ = b"e";
|
// let _ = b"e";
|
||||||
// let _ = br"f";
|
// let _ = br"f";
|
||||||
// }
|
// }
|
||||||
|
const LITERAL_FIRST: TokenSet =
|
||||||
|
token_set![TRUE_KW, FALSE_KW, INT_NUMBER, FLOAT_NUMBER, BYTE, CHAR,
|
||||||
|
STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING];
|
||||||
|
|
||||||
pub(super) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
|
pub(super) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
|
||||||
match p.current() {
|
if !LITERAL_FIRST.contains(p.current()) {
|
||||||
TRUE_KW | FALSE_KW | INT_NUMBER | FLOAT_NUMBER | BYTE | CHAR | STRING | RAW_STRING
|
return None;
|
||||||
| BYTE_STRING | RAW_BYTE_STRING => {
|
}
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
p.bump();
|
p.bump();
|
||||||
Some(m.complete(p, LITERAL))
|
Some(m.complete(p, LITERAL))
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EXPR_FIRST: TokenSet = PREFIX_EXPR_FIRST;
|
||||||
pub(super) fn expr(p: &mut Parser) {
|
pub(super) fn expr(p: &mut Parser) {
|
||||||
let mut lhs = match prefix_expr(p) {
|
let mut lhs = match prefix_expr(p) {
|
||||||
Some(lhs) => lhs,
|
Some(lhs) => lhs,
|
||||||
@@ -80,6 +82,11 @@ fn let_stmt(p: &mut Parser) {
|
|||||||
m.complete(p, LET_STMT);
|
m.complete(p, LET_STMT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PREFIX_EXPR_FIRST: TokenSet =
|
||||||
|
token_set_union![
|
||||||
|
token_set![AMPERSAND, STAR, EXCL],
|
||||||
|
ATOM_EXPR_FIRST,
|
||||||
|
];
|
||||||
fn prefix_expr(p: &mut Parser) -> Option<CompletedMarker> {
|
fn prefix_expr(p: &mut Parser) -> Option<CompletedMarker> {
|
||||||
let done = match p.current() {
|
let done = match p.current() {
|
||||||
AMPERSAND => ref_expr(p),
|
AMPERSAND => ref_expr(p),
|
||||||
@@ -128,6 +135,11 @@ fn not_expr(p: &mut Parser) -> CompletedMarker {
|
|||||||
m.complete(p, NOT_EXPR)
|
m.complete(p, NOT_EXPR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ATOM_EXPR_FIRST: TokenSet =
|
||||||
|
token_set_union![
|
||||||
|
LITERAL_FIRST,
|
||||||
|
token_set![L_PAREN, PIPE, MOVE_KW, IF_KW, UNSAFE_KW, L_CURLY, RETURN_KW],
|
||||||
|
];
|
||||||
fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
|
fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
|
||||||
match literal(p) {
|
match literal(p) {
|
||||||
Some(m) => return Some(m),
|
Some(m) => return Some(m),
|
||||||
@@ -144,6 +156,7 @@ fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
|
|||||||
IF_KW => if_expr(p),
|
IF_KW => if_expr(p),
|
||||||
UNSAFE_KW if la == L_CURLY => block_expr(p),
|
UNSAFE_KW if la == L_CURLY => block_expr(p),
|
||||||
L_CURLY => block_expr(p),
|
L_CURLY => block_expr(p),
|
||||||
|
RETURN_KW => return_expr(p),
|
||||||
_ => {
|
_ => {
|
||||||
p.err_and_bump("expected expression");
|
p.err_and_bump("expected expression");
|
||||||
return None;
|
return None;
|
||||||
@@ -237,6 +250,21 @@ fn block_expr(p: &mut Parser) -> CompletedMarker {
|
|||||||
m.complete(p, BLOCK_EXPR)
|
m.complete(p, BLOCK_EXPR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test return_expr
|
||||||
|
// fn foo() {
|
||||||
|
// return;
|
||||||
|
// return 92;
|
||||||
|
// }
|
||||||
|
fn return_expr(p: &mut Parser) -> CompletedMarker {
|
||||||
|
assert!(p.at(RETURN_KW));
|
||||||
|
let m = p.start();
|
||||||
|
p.bump();
|
||||||
|
if EXPR_FIRST.contains(p.current()) {
|
||||||
|
expr(p);
|
||||||
|
}
|
||||||
|
m.complete(p, RETURN_EXPR)
|
||||||
|
}
|
||||||
|
|
||||||
// test call_expr
|
// test call_expr
|
||||||
// fn foo() {
|
// fn foo() {
|
||||||
// let _ = f();
|
// let _ = f();
|
||||||
|
|||||||
@@ -3,22 +3,22 @@ use {
|
|||||||
SyntaxKind::{self, ERROR},
|
SyntaxKind::{self, ERROR},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) struct TokenSet {
|
#[derive(Clone, Copy)]
|
||||||
pub tokens: &'static [SyntaxKind],
|
pub(crate) struct TokenSet(pub(crate) u128);
|
||||||
|
fn mask(kind: SyntaxKind) -> u128 {
|
||||||
|
1u128 << (kind as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenSet {
|
impl TokenSet {
|
||||||
pub fn contains(&self, kind: SyntaxKind) -> bool {
|
pub fn contains(&self, kind: SyntaxKind) -> bool {
|
||||||
self.tokens.contains(&kind)
|
self.0 & mask(kind) != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! token_set {
|
macro_rules! token_set {
|
||||||
($($t:ident),*) => {
|
($($t:ident),*) => {
|
||||||
TokenSet {
|
TokenSet($(1u128 << ($t as usize))|*)
|
||||||
tokens: &[$($t),*],
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
($($t:ident),* ,) => {
|
($($t:ident),* ,) => {
|
||||||
@@ -26,6 +26,17 @@ macro_rules! token_set {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! token_set_union {
|
||||||
|
($($ts:expr),*) => {
|
||||||
|
TokenSet($($ts.0)|*)
|
||||||
|
};
|
||||||
|
|
||||||
|
($($ts:expr),* ,) => {
|
||||||
|
token_set_union!($($ts),*)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// `Parser` struct provides the low-level API for
|
/// `Parser` struct provides the low-level API for
|
||||||
/// navigating through the stream of tokens and
|
/// navigating through the stream of tokens and
|
||||||
/// constructing the parse tree. The actual parsing
|
/// constructing the parse tree. The actual parsing
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ pub enum SyntaxKind {
|
|||||||
REF_KW,
|
REF_KW,
|
||||||
LET_KW,
|
LET_KW,
|
||||||
MOVE_KW,
|
MOVE_KW,
|
||||||
|
RETURN_KW,
|
||||||
AUTO_KW,
|
AUTO_KW,
|
||||||
DEFAULT_KW,
|
DEFAULT_KW,
|
||||||
UNION_KW,
|
UNION_KW,
|
||||||
@@ -129,6 +130,8 @@ pub enum SyntaxKind {
|
|||||||
STRUCT_LIT,
|
STRUCT_LIT,
|
||||||
STRUCT_LIT_FIELD,
|
STRUCT_LIT_FIELD,
|
||||||
IF_EXPR,
|
IF_EXPR,
|
||||||
|
BLOCK_EXPR,
|
||||||
|
RETURN_EXPR,
|
||||||
EXTERN_BLOCK_EXPR,
|
EXTERN_BLOCK_EXPR,
|
||||||
ENUM_VARIANT,
|
ENUM_VARIANT,
|
||||||
NAMED_FIELD,
|
NAMED_FIELD,
|
||||||
@@ -145,7 +148,6 @@ pub enum SyntaxKind {
|
|||||||
ABI,
|
ABI,
|
||||||
NAME,
|
NAME,
|
||||||
NAME_REF,
|
NAME_REF,
|
||||||
BLOCK_EXPR,
|
|
||||||
LET_STMT,
|
LET_STMT,
|
||||||
EXPR_STMT,
|
EXPR_STMT,
|
||||||
TYPE_PARAM_LIST,
|
TYPE_PARAM_LIST,
|
||||||
@@ -202,6 +204,7 @@ impl SyntaxKind {
|
|||||||
| REF_KW
|
| REF_KW
|
||||||
| LET_KW
|
| LET_KW
|
||||||
| MOVE_KW
|
| MOVE_KW
|
||||||
|
| RETURN_KW
|
||||||
| AUTO_KW
|
| AUTO_KW
|
||||||
| DEFAULT_KW
|
| DEFAULT_KW
|
||||||
| UNION_KW
|
| UNION_KW
|
||||||
@@ -278,6 +281,7 @@ impl SyntaxKind {
|
|||||||
REF_KW => &SyntaxInfo { name: "REF_KW" },
|
REF_KW => &SyntaxInfo { name: "REF_KW" },
|
||||||
LET_KW => &SyntaxInfo { name: "LET_KW" },
|
LET_KW => &SyntaxInfo { name: "LET_KW" },
|
||||||
MOVE_KW => &SyntaxInfo { name: "MOVE_KW" },
|
MOVE_KW => &SyntaxInfo { name: "MOVE_KW" },
|
||||||
|
RETURN_KW => &SyntaxInfo { name: "RETURN_KW" },
|
||||||
AUTO_KW => &SyntaxInfo { name: "AUTO_KW" },
|
AUTO_KW => &SyntaxInfo { name: "AUTO_KW" },
|
||||||
DEFAULT_KW => &SyntaxInfo { name: "DEFAULT_KW" },
|
DEFAULT_KW => &SyntaxInfo { name: "DEFAULT_KW" },
|
||||||
UNION_KW => &SyntaxInfo { name: "UNION_KW" },
|
UNION_KW => &SyntaxInfo { name: "UNION_KW" },
|
||||||
@@ -336,6 +340,8 @@ impl SyntaxKind {
|
|||||||
STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" },
|
STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" },
|
||||||
STRUCT_LIT_FIELD => &SyntaxInfo { name: "STRUCT_LIT_FIELD" },
|
STRUCT_LIT_FIELD => &SyntaxInfo { name: "STRUCT_LIT_FIELD" },
|
||||||
IF_EXPR => &SyntaxInfo { name: "IF_EXPR" },
|
IF_EXPR => &SyntaxInfo { name: "IF_EXPR" },
|
||||||
|
BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" },
|
||||||
|
RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" },
|
||||||
EXTERN_BLOCK_EXPR => &SyntaxInfo { name: "EXTERN_BLOCK_EXPR" },
|
EXTERN_BLOCK_EXPR => &SyntaxInfo { name: "EXTERN_BLOCK_EXPR" },
|
||||||
ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" },
|
ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" },
|
||||||
NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
|
NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
|
||||||
@@ -352,7 +358,6 @@ impl SyntaxKind {
|
|||||||
ABI => &SyntaxInfo { name: "ABI" },
|
ABI => &SyntaxInfo { name: "ABI" },
|
||||||
NAME => &SyntaxInfo { name: "NAME" },
|
NAME => &SyntaxInfo { name: "NAME" },
|
||||||
NAME_REF => &SyntaxInfo { name: "NAME_REF" },
|
NAME_REF => &SyntaxInfo { name: "NAME_REF" },
|
||||||
BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" },
|
|
||||||
LET_STMT => &SyntaxInfo { name: "LET_STMT" },
|
LET_STMT => &SyntaxInfo { name: "LET_STMT" },
|
||||||
EXPR_STMT => &SyntaxInfo { name: "EXPR_STMT" },
|
EXPR_STMT => &SyntaxInfo { name: "EXPR_STMT" },
|
||||||
TYPE_PARAM_LIST => &SyntaxInfo { name: "TYPE_PARAM_LIST" },
|
TYPE_PARAM_LIST => &SyntaxInfo { name: "TYPE_PARAM_LIST" },
|
||||||
@@ -403,6 +408,7 @@ impl SyntaxKind {
|
|||||||
"ref" => REF_KW,
|
"ref" => REF_KW,
|
||||||
"let" => LET_KW,
|
"let" => LET_KW,
|
||||||
"move" => MOVE_KW,
|
"move" => MOVE_KW,
|
||||||
|
"return" => RETURN_KW,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some(kw)
|
Some(kw)
|
||||||
@@ -506,6 +512,7 @@ impl SyntaxKind {
|
|||||||
REF_KW => "ref",
|
REF_KW => "ref",
|
||||||
LET_KW => "let",
|
LET_KW => "let",
|
||||||
MOVE_KW => "move",
|
MOVE_KW => "move",
|
||||||
|
RETURN_KW => "return",
|
||||||
AUTO_KW => "auto",
|
AUTO_KW => "auto",
|
||||||
DEFAULT_KW => "default",
|
DEFAULT_KW => "default",
|
||||||
UNION_KW => "union",
|
UNION_KW => "union",
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
fn use struct trait enum impl true false as extern crate
|
fn use struct trait enum impl true false as extern crate
|
||||||
mod pub self super in where for loop while if match const
|
mod pub self super in where for loop while if match const
|
||||||
static mut type ref let else move
|
static mut type ref let else move return
|
||||||
|
|||||||
@@ -57,4 +57,6 @@ WHITESPACE 1 " "
|
|||||||
ELSE_KW 4 "else"
|
ELSE_KW 4 "else"
|
||||||
WHITESPACE 1 " "
|
WHITESPACE 1 " "
|
||||||
MOVE_KW 4 "move"
|
MOVE_KW 4 "move"
|
||||||
|
WHITESPACE 1 " "
|
||||||
|
RETURN_KW 6 "return"
|
||||||
WHITESPACE 1 "\n"
|
WHITESPACE 1 "\n"
|
||||||
|
|||||||
4
tests/data/parser/inline/0068_return_expr.rs
Normal file
4
tests/data/parser/inline/0068_return_expr.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
fn foo() {
|
||||||
|
return;
|
||||||
|
return 92;
|
||||||
|
}
|
||||||
28
tests/data/parser/inline/0068_return_expr.txt
Normal file
28
tests/data/parser/inline/0068_return_expr.txt
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
FILE@[0; 40)
|
||||||
|
FN_ITEM@[0; 40)
|
||||||
|
FN_KW@[0; 2)
|
||||||
|
NAME@[2; 6)
|
||||||
|
WHITESPACE@[2; 3)
|
||||||
|
IDENT@[3; 6) "foo"
|
||||||
|
PARAM_LIST@[6; 9)
|
||||||
|
L_PAREN@[6; 7)
|
||||||
|
R_PAREN@[7; 8)
|
||||||
|
WHITESPACE@[8; 9)
|
||||||
|
BLOCK_EXPR@[9; 40)
|
||||||
|
L_CURLY@[9; 10)
|
||||||
|
EXPR_STMT@[10; 27)
|
||||||
|
RETURN_EXPR@[10; 21)
|
||||||
|
WHITESPACE@[10; 15)
|
||||||
|
RETURN_KW@[15; 21)
|
||||||
|
SEMI@[21; 22)
|
||||||
|
WHITESPACE@[22; 27)
|
||||||
|
EXPR_STMT@[27; 38)
|
||||||
|
RETURN_EXPR@[27; 36)
|
||||||
|
RETURN_KW@[27; 33)
|
||||||
|
LITERAL@[33; 36)
|
||||||
|
WHITESPACE@[33; 34)
|
||||||
|
INT_NUMBER@[34; 36) "92"
|
||||||
|
SEMI@[36; 37)
|
||||||
|
WHITESPACE@[37; 38)
|
||||||
|
R_CURLY@[38; 39)
|
||||||
|
WHITESPACE@[39; 40)
|
||||||
Reference in New Issue
Block a user