This commit is contained in:
Aleksey Kladov 2018-08-04 16:34:54 +03:00
parent 4e4ad3d27c
commit 23cbe7fd4a
7 changed files with 184 additions and 35 deletions

View file

@ -130,23 +130,32 @@ Grammar(
"STRUCT_PAT",
"TUPLE_PAT",
// atoms
"TUPLE_EXPR",
"PATH_EXPR",
"CALL_EXPR",
"METHOD_CALL_EXPR",
"FIELD_EXPR",
"REF_EXPR",
"DEREF_EXPR",
"NOT_EXPR",
"LAMBDA_EXPR",
"STRUCT_LIT",
"STRUCT_LIT_FIELD",
"IF_EXPR",
"BLOCK_EXPR",
"RETURN_EXPR",
"MATCH_EXPR",
"MATCH_ARM",
"MATCH_GUARD",
"STRUCT_LIT",
"STRUCT_LIT_FIELD",
// postfix
"CALL_EXPR",
"METHOD_CALL_EXPR",
"FIELD_EXPR",
"TRY_EXPR",
// unary
"REF_EXPR",
"DEREF_EXPR",
"NOT_EXPR",
"BIN_EXPR",
"EXTERN_BLOCK_EXPR",
"ENUM_VARIANT",

View file

@ -29,11 +29,54 @@ pub(super) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
const EXPR_FIRST: TokenSet = PREFIX_EXPR_FIRST;
pub(super) fn expr(p: &mut Parser) {
let mut lhs = match prefix_expr(p) {
expr_bp(p, 1)
}
fn bp_of(op: SyntaxKind) -> u8 {
match op {
EQEQ | NEQ => 1,
MINUS | PLUS => 2,
STAR | SLASH => 3,
_ => 0
}
}
// test expr_binding_power
// fn foo() {
// 1 + 2 * 3 == 1 * 2 + 3
// }
// Parses expression with binding power of at least bp.
fn expr_bp(p: &mut Parser, bp: u8) {
let mut lhs = match unary_expr(p) {
Some(lhs) => lhs,
None => return,
};
loop {
let op_bp = bp_of(p.current());
if op_bp < bp {
break;
}
lhs = bin_expr(p, lhs, op_bp);
}
}
fn unary_expr(p: &mut Parser) -> Option<CompletedMarker> {
let done = match p.current() {
AMPERSAND => ref_expr(p),
STAR => deref_expr(p),
EXCL => not_expr(p),
_ => {
let lhs = atom_expr(p)?;
postfix_expr(p, lhs)
}
};
Some(done)
}
fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker {
loop {
lhs = match p.current() {
L_PAREN => call_expr(p, lhs),
@ -43,9 +86,11 @@ pub(super) fn expr(p: &mut Parser) {
field_expr(p, lhs)
},
DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs),
QUESTION => try_expr(p, lhs),
_ => break,
}
}
lhs
}
// test block
@ -89,16 +134,6 @@ const PREFIX_EXPR_FIRST: TokenSet =
ATOM_EXPR_FIRST,
];
fn prefix_expr(p: &mut Parser) -> Option<CompletedMarker> {
let done = match p.current() {
AMPERSAND => ref_expr(p),
STAR => deref_expr(p),
EXCL => not_expr(p),
_ => return atom_expr(p),
};
Some(done)
}
// test ref_expr
// fn foo() {
// let _ = &1;
@ -369,6 +404,17 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
m.complete(p, FIELD_EXPR)
}
// test try_expr
// fn foo() {
// x?;
// }
fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
assert!(p.at(QUESTION));
let m = lhs.precede(p);
p.bump();
m.complete(p, TRY_EXPR)
}
fn arg_list(p: &mut Parser) {
assert!(p.at(L_PAREN));
let m = p.start();
@ -432,3 +478,14 @@ fn struct_lit(p: &mut Parser) {
}
p.expect(R_CURLY);
}
fn bin_expr(p: &mut Parser, lhs: CompletedMarker, bp: u8) -> CompletedMarker {
assert!(match p.current() {
MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true,
_ => false,
});
let m = lhs.precede(p);
p.bump();
expr_bp(p, bp);
m.complete(p, BIN_EXPR)
}

View file

@ -123,21 +123,23 @@ pub enum SyntaxKind {
TUPLE_PAT,
TUPLE_EXPR,
PATH_EXPR,
CALL_EXPR,
METHOD_CALL_EXPR,
FIELD_EXPR,
REF_EXPR,
DEREF_EXPR,
NOT_EXPR,
LAMBDA_EXPR,
STRUCT_LIT,
STRUCT_LIT_FIELD,
IF_EXPR,
BLOCK_EXPR,
RETURN_EXPR,
MATCH_EXPR,
MATCH_ARM,
MATCH_GUARD,
STRUCT_LIT,
STRUCT_LIT_FIELD,
CALL_EXPR,
METHOD_CALL_EXPR,
FIELD_EXPR,
TRY_EXPR,
REF_EXPR,
DEREF_EXPR,
NOT_EXPR,
BIN_EXPR,
EXTERN_BLOCK_EXPR,
ENUM_VARIANT,
NAMED_FIELD,
@ -339,21 +341,23 @@ impl SyntaxKind {
TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" },
TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" },
PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" },
CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" },
METHOD_CALL_EXPR => &SyntaxInfo { name: "METHOD_CALL_EXPR" },
FIELD_EXPR => &SyntaxInfo { name: "FIELD_EXPR" },
REF_EXPR => &SyntaxInfo { name: "REF_EXPR" },
DEREF_EXPR => &SyntaxInfo { name: "DEREF_EXPR" },
NOT_EXPR => &SyntaxInfo { name: "NOT_EXPR" },
LAMBDA_EXPR => &SyntaxInfo { name: "LAMBDA_EXPR" },
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" },
MATCH_EXPR => &SyntaxInfo { name: "MATCH_EXPR" },
MATCH_ARM => &SyntaxInfo { name: "MATCH_ARM" },
MATCH_GUARD => &SyntaxInfo { name: "MATCH_GUARD" },
STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" },
STRUCT_LIT_FIELD => &SyntaxInfo { name: "STRUCT_LIT_FIELD" },
CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" },
METHOD_CALL_EXPR => &SyntaxInfo { name: "METHOD_CALL_EXPR" },
FIELD_EXPR => &SyntaxInfo { name: "FIELD_EXPR" },
TRY_EXPR => &SyntaxInfo { name: "TRY_EXPR" },
REF_EXPR => &SyntaxInfo { name: "REF_EXPR" },
DEREF_EXPR => &SyntaxInfo { name: "DEREF_EXPR" },
NOT_EXPR => &SyntaxInfo { name: "NOT_EXPR" },
BIN_EXPR => &SyntaxInfo { name: "BIN_EXPR" },
EXTERN_BLOCK_EXPR => &SyntaxInfo { name: "EXTERN_BLOCK_EXPR" },
ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" },
NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },

View file

@ -0,0 +1,3 @@
fn foo() {
1 + 2 * 3 == 1 * 2 + 3
}

View file

@ -0,0 +1,48 @@
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)
BIN_EXPR@[10; 38)
BIN_EXPR@[10; 25)
LITERAL@[10; 17)
WHITESPACE@[10; 15)
INT_NUMBER@[15; 16) "1"
WHITESPACE@[16; 17)
PLUS@[17; 18)
BIN_EXPR@[18; 25)
LITERAL@[18; 21)
WHITESPACE@[18; 19)
INT_NUMBER@[19; 20) "2"
WHITESPACE@[20; 21)
STAR@[21; 22)
LITERAL@[22; 25)
WHITESPACE@[22; 23)
INT_NUMBER@[23; 24) "3"
WHITESPACE@[24; 25)
EQEQ@[25; 27)
BIN_EXPR@[27; 38)
BIN_EXPR@[27; 34)
LITERAL@[27; 30)
WHITESPACE@[27; 28)
INT_NUMBER@[28; 29) "1"
WHITESPACE@[29; 30)
STAR@[30; 31)
LITERAL@[31; 34)
WHITESPACE@[31; 32)
INT_NUMBER@[32; 33) "2"
WHITESPACE@[33; 34)
PLUS@[34; 35)
LITERAL@[35; 38)
WHITESPACE@[35; 36)
INT_NUMBER@[36; 37) "3"
WHITESPACE@[37; 38)
R_CURLY@[38; 39)
WHITESPACE@[39; 40)

View file

@ -0,0 +1,3 @@
fn foo() {
x?;
}

View file

@ -0,0 +1,25 @@
FILE@[0; 21)
FN_ITEM@[0; 21)
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; 21)
L_CURLY@[9; 10)
EXPR_STMT@[10; 19)
TRY_EXPR@[10; 17)
PATH_EXPR@[10; 16)
PATH@[10; 16)
PATH_SEGMENT@[10; 16)
NAME_REF@[10; 16)
WHITESPACE@[10; 15)
IDENT@[15; 16) "x"
QUESTION@[16; 17)
SEMI@[17; 18)
WHITESPACE@[18; 19)
R_CURLY@[19; 20)
WHITESPACE@[20; 21)