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

View File

@@ -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();

View File

@@ -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

View File

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

View File

@@ -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

View File

@@ -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"

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)