Skip to content

Commit a99b621

Browse files
parser: support group use statements
1 parent fa820ba commit a99b621

File tree

2 files changed

+65
-18
lines changed

2 files changed

+65
-18
lines changed

src/ast.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ pub enum Statement {
304304
uses: Vec<Use>,
305305
kind: UseKind,
306306
},
307+
GroupUse {
308+
prefix: Identifier,
309+
kind: UseKind,
310+
uses: Vec<Use>,
311+
},
307312
Comment {
308313
comment: ByteString,
309314
},

src/parser/mod.rs

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -224,31 +224,62 @@ impl Parser {
224224
_ => UseKind::Normal,
225225
};
226226

227-
let mut uses = Vec::new();
228-
while !self.is_eof() {
229-
let name = self.full_name()?;
230-
let mut alias = None;
227+
if self.peek.kind == TokenKind::LeftBrace {
228+
let prefix = self.full_name()?;
229+
self.next();
231230

232-
if self.current.kind == TokenKind::As {
233-
self.next();
234-
alias = Some(self.ident()?.into());
235-
}
231+
let mut uses = Vec::new();
232+
while self.current.kind != TokenKind::RightBrace {
233+
let name = self.full_name()?;
234+
let mut alias = None;
235+
236+
if self.current.kind == TokenKind::As {
237+
self.next();
238+
alias = Some(self.ident()?.into());
239+
}
236240

237-
uses.push(Use {
238-
name: name.into(),
239-
alias,
240-
});
241+
uses.push(Use {
242+
name: name.into(),
243+
alias,
244+
});
241245

242-
if self.current.kind == TokenKind::Comma {
243-
self.next();
244-
continue;
246+
if self.current.kind == TokenKind::Comma {
247+
self.next();
248+
continue;
249+
}
245250
}
246251

252+
self.rbrace()?;
247253
self.semi()?;
248-
break;
249-
}
250254

251-
Statement::Use { uses, kind }
255+
Statement::GroupUse { prefix: prefix.into(), kind, uses }
256+
} else {
257+
let mut uses = Vec::new();
258+
while !self.is_eof() {
259+
let name = self.full_name()?;
260+
let mut alias = None;
261+
262+
if self.current.kind == TokenKind::As {
263+
self.next();
264+
alias = Some(self.ident()?.into());
265+
}
266+
267+
uses.push(Use {
268+
name: name.into(),
269+
alias,
270+
});
271+
272+
if self.current.kind == TokenKind::Comma {
273+
self.next();
274+
continue;
275+
}
276+
277+
self.semi()?;
278+
break;
279+
}
280+
281+
Statement::Use { uses, kind }
282+
}
252283
}
253284
TokenKind::Const => {
254285
self.next();
@@ -5299,6 +5330,17 @@ mod tests {
52995330
]);
53005331
}
53015332

5333+
#[test]
5334+
fn simple_group_use() {
5335+
assert_ast("<?php use Foo\\{Bar, Baz, Car};", &[
5336+
Statement::GroupUse { prefix: "Foo\\".into(), kind: crate::UseKind::Normal, uses: vec![
5337+
Use { name: "Bar".into(), alias: None },
5338+
Use { name: "Baz".into(), alias: None },
5339+
Use { name: "Car".into(), alias: None }
5340+
]}
5341+
]);
5342+
}
5343+
53025344
fn assert_ast(source: &str, expected: &[Statement]) {
53035345
let mut lexer = Lexer::new(None);
53045346
let tokens = lexer.tokenize(source).unwrap();

0 commit comments

Comments
 (0)