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