grammar: Make UseTree less ultra-janky
This commit is contained in:
parent
5341631781
commit
e36a684422
@ -228,15 +228,17 @@ pub enum ImplKind {
|
|||||||
/// An import of nonlocal [Item]s
|
/// An import of nonlocal [Item]s
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Use {
|
pub struct Use {
|
||||||
|
pub absolute: bool,
|
||||||
pub tree: UseTree,
|
pub tree: UseTree,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A tree of [Item] imports
|
/// A tree of [Item] imports
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum UseTree {
|
pub enum UseTree {
|
||||||
Tree(Path, Vec<UseTree>),
|
Tree(Vec<UseTree>),
|
||||||
Alias(Path, Identifier),
|
Path(PathPart, Box<UseTree>),
|
||||||
Path(Path),
|
Alias(Identifier, Identifier),
|
||||||
|
Name(Identifier),
|
||||||
Glob,
|
Glob,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,20 +283,22 @@ mod display {
|
|||||||
|
|
||||||
impl Display for Use {
|
impl Display for Use {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let Self { tree } = self;
|
let Self { absolute, tree } = self;
|
||||||
|
if *absolute {
|
||||||
|
write!(f, "use ::{tree}")
|
||||||
|
} else {
|
||||||
write!(f, "use {tree}")
|
write!(f, "use {tree}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for UseTree {
|
impl Display for UseTree {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
UseTree::Tree(path, tree) => {
|
UseTree::Tree(tree) => separate(tree, ", ")(f.delimit(INLINE_BRACES)),
|
||||||
write!(f, "{path}")?;
|
UseTree::Path(path, rest) => write!(f, "{path}::{rest}"),
|
||||||
separate(tree, ", ")(f.delimit(INLINE_BRACES))
|
|
||||||
}
|
|
||||||
UseTree::Alias(path, name) => write!(f, "{path} as {name}"),
|
UseTree::Alias(path, name) => write!(f, "{path} as {name}"),
|
||||||
UseTree::Path(path) => write!(f, "{path}"),
|
UseTree::Name(name) => write!(f, "{name}"),
|
||||||
UseTree::Glob => write!(f, "*"),
|
UseTree::Glob => write!(f, "*"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,8 +159,8 @@ pub trait Fold {
|
|||||||
or_fold_impl_kind(self, kind)
|
or_fold_impl_kind(self, kind)
|
||||||
}
|
}
|
||||||
fn fold_use(&mut self, u: Use) -> Use {
|
fn fold_use(&mut self, u: Use) -> Use {
|
||||||
let Use { tree } = u;
|
let Use { absolute, tree } = u;
|
||||||
Use { tree: self.fold_use_tree(tree) }
|
Use { absolute, tree: self.fold_use_tree(tree) }
|
||||||
}
|
}
|
||||||
fn fold_use_tree(&mut self, tree: UseTree) -> UseTree {
|
fn fold_use_tree(&mut self, tree: UseTree) -> UseTree {
|
||||||
or_fold_use_tree(self, tree)
|
or_fold_use_tree(self, tree)
|
||||||
@ -468,16 +468,19 @@ pub fn or_fold_impl_kind<F: Fold + ?Sized>(folder: &mut F, kind: ImplKind) -> Im
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn or_fold_use_tree<F: Fold + ?Sized>(folder: &mut F, tree: UseTree) -> UseTree {
|
pub fn or_fold_use_tree<F: Fold + ?Sized>(folder: &mut F, tree: UseTree) -> UseTree {
|
||||||
match tree {
|
match tree {
|
||||||
UseTree::Tree(path, tree) => UseTree::Tree(
|
UseTree::Tree(tree) => UseTree::Tree(
|
||||||
folder.fold_path(path),
|
|
||||||
tree.into_iter()
|
tree.into_iter()
|
||||||
.map(|tree| folder.fold_use_tree(tree))
|
.map(|tree| folder.fold_use_tree(tree))
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
),
|
||||||
|
UseTree::Path(path, rest) => UseTree::Path(
|
||||||
|
folder.fold_path_part(path),
|
||||||
|
Box::new(folder.fold_use_tree(*rest)),
|
||||||
|
),
|
||||||
UseTree::Alias(path, name) => {
|
UseTree::Alias(path, name) => {
|
||||||
UseTree::Alias(folder.fold_path(path), folder.fold_identifier(name))
|
UseTree::Alias(folder.fold_identifier(path), folder.fold_identifier(name))
|
||||||
}
|
}
|
||||||
UseTree::Path(path) => UseTree::Path(folder.fold_path(path)),
|
UseTree::Name(name) => UseTree::Name(folder.fold_identifier(name)),
|
||||||
UseTree::Glob => UseTree::Glob,
|
UseTree::Glob => UseTree::Glob,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ pub trait Visit<'a>: Sized {
|
|||||||
or_visit_impl_kind(self, target)
|
or_visit_impl_kind(self, target)
|
||||||
}
|
}
|
||||||
fn visit_use(&mut self, u: &'a Use) {
|
fn visit_use(&mut self, u: &'a Use) {
|
||||||
let Use { tree } = u;
|
let Use { absolute: _, tree } = u;
|
||||||
self.visit_use_tree(tree);
|
self.visit_use_tree(tree);
|
||||||
}
|
}
|
||||||
fn visit_use_tree(&mut self, tree: &'a UseTree) {
|
fn visit_use_tree(&mut self, tree: &'a UseTree) {
|
||||||
@ -386,15 +386,20 @@ pub fn or_visit_impl_kind<'a, V: Visit<'a>>(visitor: &mut V, target: &'a ImplKin
|
|||||||
|
|
||||||
pub fn or_visit_use_tree<'a, V: Visit<'a>>(visitor: &mut V, tree: &'a UseTree) {
|
pub fn or_visit_use_tree<'a, V: Visit<'a>>(visitor: &mut V, tree: &'a UseTree) {
|
||||||
match tree {
|
match tree {
|
||||||
UseTree::Tree(path, tree) => {
|
UseTree::Tree(tree) => {
|
||||||
visitor.visit_path(path);
|
|
||||||
tree.iter().for_each(|tree| visitor.visit_use_tree(tree));
|
tree.iter().for_each(|tree| visitor.visit_use_tree(tree));
|
||||||
}
|
}
|
||||||
|
UseTree::Path(path, rest) => {
|
||||||
|
visitor.visit_path_part(path);
|
||||||
|
visitor.visit_use_tree(rest)
|
||||||
|
}
|
||||||
UseTree::Alias(path, name) => {
|
UseTree::Alias(path, name) => {
|
||||||
visitor.visit_path(path);
|
visitor.visit_identifier(path);
|
||||||
|
visitor.visit_identifier(name);
|
||||||
|
}
|
||||||
|
UseTree::Name(name) => {
|
||||||
visitor.visit_identifier(name);
|
visitor.visit_identifier(name);
|
||||||
}
|
}
|
||||||
UseTree::Path(path) => visitor.visit_path(path),
|
|
||||||
UseTree::Glob => {}
|
UseTree::Glob => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -607,30 +607,40 @@ impl<'t> Parser<'t> {
|
|||||||
|
|
||||||
pub fn parse_use(&mut self) -> PResult<Use> {
|
pub fn parse_use(&mut self) -> PResult<Use> {
|
||||||
self.consume_peeked();
|
self.consume_peeked();
|
||||||
Ok(Use { tree: self.parse_use_tree()? })
|
let absolute = self.match_op(Punct::ColonColon, Parsing::Use).is_ok();
|
||||||
|
let tree = self.parse_use_tree()?;
|
||||||
|
self.match_op(Punct::Semi, Parsing::Use)?;
|
||||||
|
Ok(Use { tree, absolute })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_use_tree(&mut self) -> PResult<UseTree> {
|
pub fn parse_use_tree(&mut self) -> PResult<UseTree> {
|
||||||
const PARSING: Parsing = Parsing::UseTree;
|
const PARSING: Parsing = Parsing::UseTree;
|
||||||
// glob import
|
// glob import
|
||||||
if self.match_op(Punct::Star, PARSING).is_ok() {
|
Ok(match self.peek_kind(PARSING)? {
|
||||||
return Ok(UseTree::Glob);
|
TokenKind::Punct(Punct::Star) => {
|
||||||
}
|
|
||||||
let path = self.path()?;
|
|
||||||
Ok(match self.peek_kind(PARSING) {
|
|
||||||
Ok(TokenKind::As) => {
|
|
||||||
self.consume_peeked();
|
self.consume_peeked();
|
||||||
UseTree::Alias(path, self.identifier()?)
|
UseTree::Glob
|
||||||
}
|
}
|
||||||
Ok(TokenKind::Punct(Punct::LCurly)) => UseTree::Tree(
|
TokenKind::Punct(Punct::LCurly) => UseTree::Tree(delim(
|
||||||
path,
|
|
||||||
delim(
|
|
||||||
sep(Self::parse_use_tree, Punct::Comma, CURLIES.1, PARSING),
|
sep(Self::parse_use_tree, Punct::Comma, CURLIES.1, PARSING),
|
||||||
CURLIES,
|
CURLIES,
|
||||||
PARSING,
|
PARSING,
|
||||||
)(self)?,
|
)(self)?),
|
||||||
),
|
TokenKind::SelfKw | TokenKind::Super | TokenKind::Identifier => {
|
||||||
_ => UseTree::Path(path),
|
let name = self.path_part()?;
|
||||||
|
if self.match_op(Punct::ColonColon, PARSING).is_ok() {
|
||||||
|
UseTree::Path(name, Box::new(self.parse_use_tree()?))
|
||||||
|
} else {
|
||||||
|
let PathPart::Ident(name) = name else {
|
||||||
|
Err(self.error(
|
||||||
|
ErrorKind::ExpectedParsing { want: Parsing::Identifier },
|
||||||
|
PARSING,
|
||||||
|
))?
|
||||||
|
};
|
||||||
|
UseTree::Name(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t => Err(self.error(Unexpected(t), Parsing::UseTree))?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,16 +325,17 @@ pub mod yamlify {
|
|||||||
}
|
}
|
||||||
impl Yamlify for Use {
|
impl Yamlify for Use {
|
||||||
fn yaml(&self, y: &mut Yamler) {
|
fn yaml(&self, y: &mut Yamler) {
|
||||||
let Self { tree } = self;
|
let Self { absolute, tree } = self;
|
||||||
y.key("Use").yaml(tree);
|
y.key("Use").pair("absolute", absolute).yaml(tree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Yamlify for UseTree {
|
impl Yamlify for UseTree {
|
||||||
fn yaml(&self, y: &mut Yamler) {
|
fn yaml(&self, y: &mut Yamler) {
|
||||||
match self {
|
match self {
|
||||||
UseTree::Tree(path, tree) => y.pair("path", path).pair("tree", tree),
|
UseTree::Tree(trees) => y.pair("trees", trees),
|
||||||
UseTree::Alias(path, name) => y.pair("path", path).pair("name", name),
|
UseTree::Path(path, tree) => y.pair("path", path).pair("tree", tree),
|
||||||
UseTree::Path(path) => y.pair("path", path),
|
UseTree::Alias(from, to) => y.pair("from", from).pair("to", to),
|
||||||
|
UseTree::Name(name) => y.pair("name", name),
|
||||||
UseTree::Glob => y.value("Glob"),
|
UseTree::Glob => y.value("Glob"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,9 @@ Alias = "type" Identifier ('=' Ty)? ';' ;
|
|||||||
Impl = "impl" Path '{' Item* '}' ;
|
Impl = "impl" Path '{' Item* '}' ;
|
||||||
(* TODO: Impl Trait for Target*)
|
(* TODO: Impl Trait for Target*)
|
||||||
|
|
||||||
Use = "use" UseTree ;
|
Use = "use" '::'? UseTree ';' ;
|
||||||
UseTree = Path '{' (UseTree ',')* UseTree? '}'
|
UseTree = '*' | '{' (UseTree ',')* UseTree? '}'
|
||||||
| Path "as" Identifier
|
| PathPart ('::' UseTree | "as" Identifier)? ;
|
||||||
| Path | '*' ;
|
|
||||||
|
|
||||||
(* type *)
|
(* type *)
|
||||||
Ty = Never | Empty | Path | TyTuple | TyRef | TyFn ;
|
Ty = Never | Empty | Path | TyTuple | TyRef | TyFn ;
|
||||||
|
Loading…
Reference in New Issue
Block a user