2018-01-07 19:46:10 +01:00
|
|
|
use super::*;
|
|
|
|
|
2018-07-30 15:16:58 +02:00
|
|
|
// test expr_literals
|
|
|
|
// fn foo() {
|
2018-07-30 16:02:51 +02:00
|
|
|
// 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";
|
2018-07-30 15:16:58 +02:00
|
|
|
// }
|
2018-07-31 11:26:19 +02:00
|
|
|
pub(super) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
|
2018-01-20 19:49:58 +01:00
|
|
|
match p.current() {
|
2018-01-28 00:31:23 +01:00
|
|
|
TRUE_KW | FALSE_KW | INT_NUMBER | FLOAT_NUMBER | BYTE | CHAR | STRING | RAW_STRING
|
|
|
|
| BYTE_STRING | RAW_BYTE_STRING => {
|
2018-07-31 11:26:19 +02:00
|
|
|
let m = p.start();
|
2018-01-20 19:49:58 +01:00
|
|
|
p.bump();
|
2018-07-31 11:26:19 +02:00
|
|
|
Some(m.complete(p, LITERAL))
|
2018-01-20 19:49:58 +01:00
|
|
|
}
|
2018-07-31 11:26:19 +02:00
|
|
|
_ => None,
|
2018-01-20 19:49:58 +01:00
|
|
|
}
|
|
|
|
}
|
2018-01-28 20:59:18 +01:00
|
|
|
|
|
|
|
pub(super) fn expr(p: &mut Parser) {
|
2018-07-31 16:35:54 +02:00
|
|
|
let mut lhs = match prefix_expr(p) {
|
|
|
|
Some(lhs) => lhs,
|
|
|
|
None => return,
|
|
|
|
};
|
2018-07-31 11:26:19 +02:00
|
|
|
|
2018-07-31 16:35:54 +02:00
|
|
|
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)
|
|
|
|
}
|
2018-07-31 11:26:19 +02:00
|
|
|
_ => break,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-31 11:51:00 +02:00
|
|
|
fn prefix_expr(p: &mut Parser) -> Option<CompletedMarker> {
|
|
|
|
match p.current() {
|
|
|
|
AMPERSAND => Some(ref_expr(p)),
|
2018-07-31 19:44:54 +02:00
|
|
|
STAR => Some(deref_expr(p)),
|
2018-07-31 14:40:40 +02:00
|
|
|
_ => atom_expr(p),
|
2018-07-31 11:51:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
|
2018-07-31 19:44:54 +02:00
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
|
2018-07-31 11:26:19 +02:00
|
|
|
fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
|
|
|
|
match literal(p) {
|
|
|
|
Some(m) => return Some(m),
|
|
|
|
None => (),
|
2018-01-28 20:59:18 +01:00
|
|
|
}
|
2018-07-30 16:02:51 +02:00
|
|
|
if paths::is_path_start(p) {
|
2018-07-31 11:26:19 +02:00
|
|
|
return Some(path_expr(p));
|
2018-07-30 16:02:51 +02:00
|
|
|
}
|
2018-02-17 23:06:48 +01:00
|
|
|
|
|
|
|
match p.current() {
|
2018-07-31 11:26:19 +02:00
|
|
|
L_PAREN => Some(tuple_expr(p)),
|
|
|
|
_ => {
|
2018-07-31 12:41:30 +02:00
|
|
|
p.err_and_bump("expected expression");
|
2018-07-31 11:26:19 +02:00
|
|
|
None
|
|
|
|
}
|
2018-02-17 23:06:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-31 11:26:19 +02:00
|
|
|
fn tuple_expr(p: &mut Parser) -> CompletedMarker {
|
2018-02-17 23:06:48 +01:00
|
|
|
assert!(p.at(L_PAREN));
|
|
|
|
let m = p.start();
|
|
|
|
p.expect(L_PAREN);
|
|
|
|
p.expect(R_PAREN);
|
2018-07-31 11:26:19 +02:00
|
|
|
m.complete(p, TUPLE_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);
|
2018-07-31 11:32:53 +02:00
|
|
|
arg_list(p);
|
|
|
|
m.complete(p, CALL_EXPR)
|
|
|
|
}
|
|
|
|
|
2018-07-31 16:35:54 +02:00
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
|
2018-07-31 11:32:53 +02:00
|
|
|
fn arg_list(p: &mut Parser) {
|
|
|
|
assert!(p.at(L_PAREN));
|
|
|
|
let m = p.start();
|
2018-07-31 11:26:19 +02:00
|
|
|
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);
|
2018-07-31 11:32:53 +02:00
|
|
|
m.complete(p, ARG_LIST);
|
2018-01-28 20:59:18 +01:00
|
|
|
}
|
2018-07-30 16:02:51 +02:00
|
|
|
|
|
|
|
// test path_expr
|
|
|
|
// fn foo() {
|
|
|
|
// let _ = a;
|
|
|
|
// let _ = a::b;
|
|
|
|
// let _ = ::a::<b>;
|
|
|
|
// }
|
2018-07-31 11:26:19 +02:00
|
|
|
fn path_expr(p: &mut Parser) -> CompletedMarker {
|
2018-07-30 16:02:51 +02:00
|
|
|
assert!(paths::is_path_start(p));
|
|
|
|
let m = p.start();
|
|
|
|
paths::expr_path(p);
|
2018-07-31 19:38:36 +02:00
|
|
|
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);
|
2018-07-30 16:02:51 +02:00
|
|
|
}
|