From 23cbe7fd4a048ba44aee647b3b7d5a7f3aa575da Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 4 Aug 2018 16:34:54 +0300 Subject: Pratt --- src/grammar.ron | 25 +++++++++----- src/grammar/expressions.rs | 79 +++++++++++++++++++++++++++++++++++++------ src/syntax_kinds/generated.rs | 36 +++++++++++--------- 3 files changed, 105 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/grammar.ron b/src/grammar.ron index 655ed2e40..8ce5ebc49 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -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", diff --git a/src/grammar/expressions.rs b/src/grammar/expressions.rs index 6506892e1..ecca2a3f9 100644 --- a/src/grammar/expressions.rs +++ b/src/grammar/expressions.rs @@ -29,11 +29,54 @@ pub(super) fn literal(p: &mut Parser) -> Option { 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 { + 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 { - 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) +} diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index d7a57f4d0..7bdd0267c 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -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" }, -- cgit v1.2.3