Skip to content

Commit 4927533

Browse files
committed
Parse generic qualified calls
1 parent 87b674e commit 4927533

2 files changed

Lines changed: 57 additions & 18 deletions

File tree

src/syntax/parser.rs

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -571,24 +571,8 @@ fn parse_expr(tokens: &[Token], start: usize, end: usize) -> Option<Expr> {
571571
}
572572

573573
fn parse_call_expr(tokens: &[Token], start: usize, end: usize) -> Option<Expr> {
574-
let (callee, open) = if tokens.get(start + 1).is_some_and(|token| token.symbol("(")) {
575-
(
576-
Callee::Name(ident_name(tokens.get(start)?)?.to_string()),
577-
start + 1,
578-
)
579-
} else if tokens.get(start + 1).is_some_and(|token| token.symbol("."))
580-
&& tokens.get(start + 3).is_some_and(|token| token.symbol("("))
581-
{
582-
(
583-
Callee::Qualified {
584-
namespace: ident_name(tokens.get(start)?)?.to_string(),
585-
name: ident_name(tokens.get(start + 2)?)?.to_string(),
586-
},
587-
start + 3,
588-
)
589-
} else {
590-
return None;
591-
};
574+
let open = find_call_open(tokens, start, end)?;
575+
let callee = parse_callee(tokens, start, open)?;
592576
let close = find_matching(tokens, open, "(", ")")?;
593577
if close >= end {
594578
return None;
@@ -601,6 +585,47 @@ fn parse_call_expr(tokens: &[Token], start: usize, end: usize) -> Option<Expr> {
601585
})
602586
}
603587

588+
fn find_call_open(tokens: &[Token], start: usize, end: usize) -> Option<usize> {
589+
let mut depth = 0usize;
590+
for (index, token) in tokens.iter().enumerate().take(end).skip(start + 1) {
591+
if depth == 0 && token.symbol("(") {
592+
return Some(index);
593+
}
594+
if token.symbol("<") || token.symbol("[") {
595+
depth += 1;
596+
} else if token.symbol(">") || token.symbol("]") {
597+
depth = depth.saturating_sub(1);
598+
}
599+
}
600+
None
601+
}
602+
603+
fn parse_callee(tokens: &[Token], start: usize, end: usize) -> Option<Callee> {
604+
if start + 1 == end {
605+
return Some(Callee::Name(ident_name(tokens.get(start)?)?.to_string()));
606+
}
607+
608+
let dot = find_top_level_dot(tokens, start, end)?;
609+
let namespace = parse_type_ref(tokens, start, dot)?.name;
610+
let name = ident_name(tokens.get(dot + 1)?)?.to_string();
611+
Some(Callee::Qualified { namespace, name })
612+
}
613+
614+
fn find_top_level_dot(tokens: &[Token], start: usize, end: usize) -> Option<usize> {
615+
let mut depth = 0usize;
616+
for (index, token) in tokens.iter().enumerate().take(end).skip(start) {
617+
if depth == 0 && token.symbol(".") {
618+
return Some(index);
619+
}
620+
if token.symbol("<") || token.symbol("[") {
621+
depth += 1;
622+
} else if token.symbol(">") || token.symbol("]") {
623+
depth = depth.saturating_sub(1);
624+
}
625+
}
626+
None
627+
}
628+
604629
fn parse_field_expr(tokens: &[Token], start: usize, end: usize) -> Option<Expr> {
605630
if start + 2 >= end || !tokens.get(start + 1).is_some_and(|token| token.symbol(".")) {
606631
return None;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// expect: RS0202
2+
mode: uses-local
3+
4+
resource DbConnection {
5+
fd: Int
6+
7+
drop {
8+
Db.close(fd: fd)
9+
}
10+
}
11+
12+
fn bad_borrow(pool: mut ResourcePool<DbConnection>) -> Unit {
13+
ResourcePool<DbConnection>.borrow(pool: pool)
14+
}

0 commit comments

Comments
 (0)