From 7912189ec304b28c4df0030b5282cf3d21074154 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Jul 2018 23:38:19 +0300 Subject: reorganize --- src/grammar/expressions.rs | 284 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 src/grammar/expressions.rs (limited to 'src/grammar/expressions.rs') diff --git a/src/grammar/expressions.rs b/src/grammar/expressions.rs new file mode 100644 index 000000000..06f9105c6 --- /dev/null +++ b/src/grammar/expressions.rs @@ -0,0 +1,284 @@ +use super::*; + +// test expr_literals +// fn foo() { +// let _ = true; +// let _ = false; +// let _ = 1; +// let _ = 2.0; +// let _ = b'a'; +// let _ = 'b'; +// let _ = "c"; +// let _ = r"d"; +// let _ = b"e"; +// let _ = br"f"; +// } +pub(super) fn literal(p: &mut Parser) -> Option { + 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, + } +} + +pub(super) fn expr(p: &mut Parser) { + let mut lhs = match prefix_expr(p) { + Some(lhs) => lhs, + None => return, + }; + + loop { + lhs = match p.current() { + L_PAREN => call_expr(p, lhs), + DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN { + method_call_expr(p, lhs) + } else { + field_expr(p, lhs) + }, + _ => break, + } + } +} + +// test block +// fn a() {} +// fn b() { let _ = 1; } +// fn c() { 1; 2; } +// fn d() { 1; 2 } +pub(super) fn block(p: &mut Parser) { + if !p.at(L_CURLY) { + p.error("expected block"); + } + let m = p.start(); + p.bump(); + while !p.at(EOF) && !p.at(R_CURLY) { + match p.current() { + LET_KW => let_stmt(p), + c => { + // test block_items + // fn a() { fn b() {} } + if items::ITEM_FIRST.contains(c) { + items::item(p) + } else { + let expr_stmt = p.start(); + expressions::expr(p); + if p.eat(SEMI) { + expr_stmt.complete(p, EXPR_STMT); + } else { + expr_stmt.abandon(p); + } + } + } + } + } + p.expect(R_CURLY); + m.complete(p, BLOCK); +} + +// test let_stmt; +// fn foo() { +// let a; +// let b: i32; +// let c = 92; +// let d: i32 = 92; +// } +fn let_stmt(p: &mut Parser) { + assert!(p.at(LET_KW)); + let m = p.start(); + p.bump(); + patterns::pattern(p); + if p.at(COLON) { + types::ascription(p); + } + if p.eat(EQ) { + expressions::expr(p); + } + p.expect(SEMI); + m.complete(p, LET_STMT); +} + +fn prefix_expr(p: &mut Parser) -> Option { + match p.current() { + AMPERSAND => Some(ref_expr(p)), + STAR => Some(deref_expr(p)), + _ => atom_expr(p), + } +} + +// test ref_expr +// fn foo() { +// let _ = &1; +// let _ = &mut &f(); +// } +fn ref_expr(p: &mut Parser) -> CompletedMarker { + assert!(p.at(AMPERSAND)); + let m = p.start(); + p.bump(); + p.eat(MUT_KW); + expr(p); + m.complete(p, REF_EXPR) +} + +// test deref_expr +// fn foo() { +// **&1; +// } +fn deref_expr(p: &mut Parser) -> CompletedMarker { + assert!(p.at(STAR)); + let m = p.start(); + p.bump(); + expr(p); + m.complete(p, DEREF_EXPR) +} + +fn atom_expr(p: &mut Parser) -> Option { + match literal(p) { + Some(m) => return Some(m), + None => (), + } + if paths::is_path_start(p) { + return Some(path_expr(p)); + } + + match p.current() { + L_PAREN => Some(tuple_expr(p)), + PIPE => Some(lambda_expr(p)), + _ => { + p.err_and_bump("expected expression"); + None + } + } +} + +fn tuple_expr(p: &mut Parser) -> CompletedMarker { + assert!(p.at(L_PAREN)); + let m = p.start(); + p.expect(L_PAREN); + p.expect(R_PAREN); + m.complete(p, TUPLE_EXPR) +} + +// test lambda_expr +// fn foo() { +// || (); +// || -> i32 { 92 }; +// |x| x; +// |x: i32,| x; +// } +fn lambda_expr(p: &mut Parser) -> CompletedMarker { + assert!(p.at(PIPE)); + let m = p.start(); + params::param_list_opt_types(p); + if fn_ret_type(p) { + block(p); + } else { + expr(p) + } + m.complete(p, LAMBDA_EXPR) +} + +// test call_expr +// fn foo() { +// let _ = f(); +// let _ = f()(1)(1, 2,); +// } +fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { + assert!(p.at(L_PAREN)); + let m = lhs.precede(p); + arg_list(p); + m.complete(p, CALL_EXPR) +} + +// test method_call_expr +// fn foo() { +// x.foo(); +// y.bar(1, 2,); +// } +fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { + assert!(p.at(DOT) && p.nth(1) == IDENT && p.nth(2) == L_PAREN); + let m = lhs.precede(p); + p.bump(); + p.bump(); + arg_list(p); + m.complete(p, METHOD_CALL_EXPR) +} + +// test field_expr +// fn foo() { +// x.foo.bar; +// } +fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { + assert!(p.at(DOT) && p.nth(1) == IDENT); + let m = lhs.precede(p); + p.bump(); + p.bump(); + m.complete(p, FIELD_EXPR) +} + +fn arg_list(p: &mut Parser) { + assert!(p.at(L_PAREN)); + let m = p.start(); + p.bump(); + while !p.at(R_PAREN) && !p.at(EOF) { + expr(p); + if !p.at(R_PAREN) && !p.expect(COMMA) { + break; + } + } + p.eat(R_PAREN); + m.complete(p, ARG_LIST); +} + +// test path_expr +// fn foo() { +// let _ = a; +// let _ = a::b; +// let _ = ::a::; +// } +fn path_expr(p: &mut Parser) -> CompletedMarker { + assert!(paths::is_path_start(p)); + let m = p.start(); + paths::expr_path(p); + if p.at(L_CURLY) { + struct_lit(p); + m.complete(p, STRUCT_LIT) + } else { + m.complete(p, PATH_EXPR) + } +} + +// test struct_lit +// fn foo() { +// S {}; +// S { x, y: 32, }; +// S { x, y: 32, ..Default::default() }; +// } +fn struct_lit(p: &mut Parser) { + assert!(p.at(L_CURLY)); + p.bump(); + while !p.at(EOF) && !p.at(R_CURLY) { + match p.current() { + IDENT => { + let m = p.start(); + name_ref(p); + if p.eat(COLON) { + expr(p); + } + m.complete(p, STRUCT_LIT_FIELD); + } + DOTDOT => { + p.bump(); + expr(p); + } + _ => p.err_and_bump("expected identifier"), + } + if !p.at(R_CURLY) { + p.expect(COMMA); + } + } + p.expect(R_CURLY); +} -- cgit v1.2.3