parser: support group use statements

This commit is contained in:
Ryan Chandler 2022-11-28 13:09:45 +00:00
parent fa820ba296
commit a99b62155a
2 changed files with 67 additions and 20 deletions

View File

@ -304,6 +304,11 @@ pub enum Statement {
uses: Vec<Use>, uses: Vec<Use>,
kind: UseKind, kind: UseKind,
}, },
GroupUse {
prefix: Identifier,
kind: UseKind,
uses: Vec<Use>,
},
Comment { Comment {
comment: ByteString, comment: ByteString,
}, },

View File

@ -224,31 +224,62 @@ impl Parser {
_ => UseKind::Normal, _ => UseKind::Normal,
}; };
let mut uses = Vec::new(); if self.peek.kind == TokenKind::LeftBrace {
while !self.is_eof() { let prefix = self.full_name()?;
let name = self.full_name()?; self.next();
let mut alias = None;
if self.current.kind == TokenKind::As { let mut uses = Vec::new();
self.next(); while self.current.kind != TokenKind::RightBrace {
alias = Some(self.ident()?.into()); let name = self.full_name()?;
} let mut alias = None;
uses.push(Use { if self.current.kind == TokenKind::As {
name: name.into(), self.next();
alias, alias = Some(self.ident()?.into());
}); }
if self.current.kind == TokenKind::Comma { uses.push(Use {
self.next(); name: name.into(),
continue; alias,
});
if self.current.kind == TokenKind::Comma {
self.next();
continue;
}
} }
self.rbrace()?;
self.semi()?; self.semi()?;
break;
}
Statement::Use { uses, kind } Statement::GroupUse { prefix: prefix.into(), kind, uses }
} else {
let mut uses = Vec::new();
while !self.is_eof() {
let name = self.full_name()?;
let mut alias = None;
if self.current.kind == TokenKind::As {
self.next();
alias = Some(self.ident()?.into());
}
uses.push(Use {
name: name.into(),
alias,
});
if self.current.kind == TokenKind::Comma {
self.next();
continue;
}
self.semi()?;
break;
}
Statement::Use { uses, kind }
}
} }
TokenKind::Const => { TokenKind::Const => {
self.next(); self.next();
@ -5299,6 +5330,17 @@ mod tests {
]); ]);
} }
#[test]
fn simple_group_use() {
assert_ast("<?php use Foo\\{Bar, Baz, Car};", &[
Statement::GroupUse { prefix: "Foo\\".into(), kind: crate::UseKind::Normal, uses: vec![
Use { name: "Bar".into(), alias: None },
Use { name: "Baz".into(), alias: None },
Use { name: "Car".into(), alias: None }
]}
]);
}
fn assert_ast(source: &str, expected: &[Statement]) { fn assert_ast(source: &str, expected: &[Statement]) {
let mut lexer = Lexer::new(None); let mut lexer = Lexer::new(None);
let tokens = lexer.tokenize(source).unwrap(); let tokens = lexer.tokenize(source).unwrap();