Pratt
This commit is contained in:
parent
4e4ad3d27c
commit
23cbe7fd4a
7 changed files with 184 additions and 35 deletions
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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" },
|
||||
|
|
|
|||
3
tests/data/parser/inline/0074_expr_binding_power.rs
Normal file
3
tests/data/parser/inline/0074_expr_binding_power.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fn foo() {
|
||||
1 + 2 * 3 == 1 * 2 + 3
|
||||
}
|
||||
48
tests/data/parser/inline/0074_expr_binding_power.txt
Normal file
48
tests/data/parser/inline/0074_expr_binding_power.txt
Normal 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)
|
||||
3
tests/data/parser/inline/0075_try_expr.rs
Normal file
3
tests/data/parser/inline/0075_try_expr.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fn foo() {
|
||||
x?;
|
||||
}
|
||||
25
tests/data/parser/inline/0075_try_expr.txt
Normal file
25
tests/data/parser/inline/0075_try_expr.txt
Normal 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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue