return expr

This commit is contained in:
Aleksey Kladov 2018-08-01 11:27:31 +03:00
parent 53485030dc
commit 37e1625f01
8 changed files with 100 additions and 18 deletions

View File

@ -70,6 +70,7 @@ Grammar(
"ref",
"let",
"move",
"return",
],
contextual_keywords: [
"auto",
@ -138,6 +139,8 @@ Grammar(
"STRUCT_LIT",
"STRUCT_LIT_FIELD",
"IF_EXPR",
"BLOCK_EXPR",
"RETURN_EXPR",
"EXTERN_BLOCK_EXPR",
"ENUM_VARIANT",
@ -155,7 +158,6 @@ Grammar(
"ABI",
"NAME",
"NAME_REF",
"BLOCK_EXPR",
"LET_STMT",
"EXPR_STMT",

View File

@ -13,18 +13,20 @@
// let _ = b"e";
// 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> {
match p.current() {
TRUE_KW | FALSE_KW | INT_NUMBER | FLOAT_NUMBER | BYTE | CHAR | STRING | RAW_STRING
| BYTE_STRING | RAW_BYTE_STRING => {
let m = p.start();
p.bump();
Some(m.complete(p, LITERAL))
}
_ => None,
if !LITERAL_FIRST.contains(p.current()) {
return None;
}
let m = p.start();
p.bump();
Some(m.complete(p, LITERAL))
}
const EXPR_FIRST: TokenSet = PREFIX_EXPR_FIRST;
pub(super) fn expr(p: &mut Parser) {
let mut lhs = match prefix_expr(p) {
Some(lhs) => lhs,
@ -80,6 +82,11 @@ fn let_stmt(p: &mut Parser) {
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> {
let done = match p.current() {
AMPERSAND => ref_expr(p),
@ -128,6 +135,11 @@ fn not_expr(p: &mut Parser) -> CompletedMarker {
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> {
match literal(p) {
Some(m) => return Some(m),
@ -144,6 +156,7 @@ fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
IF_KW => if_expr(p),
UNSAFE_KW if la == L_CURLY => block_expr(p),
L_CURLY => block_expr(p),
RETURN_KW => return_expr(p),
_ => {
p.err_and_bump("expected expression");
return None;
@ -237,6 +250,21 @@ fn block_expr(p: &mut Parser) -> CompletedMarker {
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
// fn foo() {
// let _ = f();

View File

@ -3,22 +3,22 @@
SyntaxKind::{self, ERROR},
};
pub(crate) struct TokenSet {
pub tokens: &'static [SyntaxKind],
#[derive(Clone, Copy)]
pub(crate) struct TokenSet(pub(crate) u128);
fn mask(kind: SyntaxKind) -> u128 {
1u128 << (kind as usize)
}
impl TokenSet {
pub fn contains(&self, kind: SyntaxKind) -> bool {
self.tokens.contains(&kind)
self.0 & mask(kind) != 0
}
}
#[macro_export]
macro_rules! token_set {
($($t:ident),*) => {
TokenSet {
tokens: &[$($t),*],
}
TokenSet($(1u128 << ($t as usize))|*)
};
($($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
/// navigating through the stream of tokens and
/// constructing the parse tree. The actual parsing

View File

@ -71,6 +71,7 @@ pub enum SyntaxKind {
REF_KW,
LET_KW,
MOVE_KW,
RETURN_KW,
AUTO_KW,
DEFAULT_KW,
UNION_KW,
@ -129,6 +130,8 @@ pub enum SyntaxKind {
STRUCT_LIT,
STRUCT_LIT_FIELD,
IF_EXPR,
BLOCK_EXPR,
RETURN_EXPR,
EXTERN_BLOCK_EXPR,
ENUM_VARIANT,
NAMED_FIELD,
@ -145,7 +148,6 @@ pub enum SyntaxKind {
ABI,
NAME,
NAME_REF,
BLOCK_EXPR,
LET_STMT,
EXPR_STMT,
TYPE_PARAM_LIST,
@ -202,6 +204,7 @@ pub fn is_keyword(self) -> bool {
| REF_KW
| LET_KW
| MOVE_KW
| RETURN_KW
| AUTO_KW
| DEFAULT_KW
| UNION_KW
@ -278,6 +281,7 @@ pub(crate) fn info(self) -> &'static SyntaxInfo {
REF_KW => &SyntaxInfo { name: "REF_KW" },
LET_KW => &SyntaxInfo { name: "LET_KW" },
MOVE_KW => &SyntaxInfo { name: "MOVE_KW" },
RETURN_KW => &SyntaxInfo { name: "RETURN_KW" },
AUTO_KW => &SyntaxInfo { name: "AUTO_KW" },
DEFAULT_KW => &SyntaxInfo { name: "DEFAULT_KW" },
UNION_KW => &SyntaxInfo { name: "UNION_KW" },
@ -336,6 +340,8 @@ pub(crate) fn info(self) -> &'static SyntaxInfo {
STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" },
STRUCT_LIT_FIELD => &SyntaxInfo { name: "STRUCT_LIT_FIELD" },
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" },
ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" },
NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
@ -352,7 +358,6 @@ pub(crate) fn info(self) -> &'static SyntaxInfo {
ABI => &SyntaxInfo { name: "ABI" },
NAME => &SyntaxInfo { name: "NAME" },
NAME_REF => &SyntaxInfo { name: "NAME_REF" },
BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" },
LET_STMT => &SyntaxInfo { name: "LET_STMT" },
EXPR_STMT => &SyntaxInfo { name: "EXPR_STMT" },
TYPE_PARAM_LIST => &SyntaxInfo { name: "TYPE_PARAM_LIST" },
@ -403,6 +408,7 @@ pub(crate) fn from_keyword(ident: &str) -> Option<SyntaxKind> {
"ref" => REF_KW,
"let" => LET_KW,
"move" => MOVE_KW,
"return" => RETURN_KW,
_ => return None,
};
Some(kw)
@ -506,6 +512,7 @@ pub(crate) fn static_text(self) -> Option<&'static str> {
REF_KW => "ref",
LET_KW => "let",
MOVE_KW => "move",
RETURN_KW => "return",
AUTO_KW => "auto",
DEFAULT_KW => "default",
UNION_KW => "union",

View File

@ -1,3 +1,3 @@
fn use struct trait enum impl true false as extern crate
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

View File

@ -57,4 +57,6 @@ WHITESPACE 1 " "
ELSE_KW 4 "else"
WHITESPACE 1 " "
MOVE_KW 4 "move"
WHITESPACE 1 " "
RETURN_KW 6 "return"
WHITESPACE 1 "\n"

View File

@ -0,0 +1,4 @@
fn foo() {
return;
return 92;
}

View 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)